UvaLive 6435 Network Packet Ordering(dp)

点击打开链接

UvaLive 6435 Network Packet Ordering

题意:从纽约往dublin发n个数据包,告诉你每个数据包到达的理想时间ta1,ta2.....tan,但是数据包传输的实际时间是可能比理想时间晚x毫秒,x<D,但是数据包到达的相对顺序不会改变。从雅加达向dublin发m个数据包,数据包传输过程同上。问最后dublin接收两地发来的数据包的顺序有多少种?数据包到达的时间可以为小数,但是输入的数据一定是整数。

从纽约发的数据包把时间分成了n+1个区间,分别是0-ta1,ta1-ta2,ta2-ta3.....tan-无穷大。

用dp【i】【j】表示从雅加达发来的前i个数据包,第i个数据包在区间j中答案有多少种。那么转移就是,dp【i】【j】=sum(dp【i-1】【k】,1<=k<=j)。但是这样的时间复杂度和空间复杂度都太高,需要优化。首先每个数据包所在的区间不会超过200个,可以预处理出每个数据包可以在的区间,dp数组的第二维优化到200,这样空间和时间都优化下来了,仔细观察我们还可以将转移的复杂度优化到O(1),这样总时间复杂度为O(n*200*15)。详情见代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
#define nn 51000
#define inff 0x3fffffff
#define mod 1000000009
using namespace std;
typedef long long LL;
int n,m,d;
int ta[nn],tb[nn];
vector<int>ve[nn];
LL dp[nn][220];
int main()
{
    int t,i,j;
    int cas=1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&d);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&ta[i]);
        }
        for(i=1;i<=m;i++)
        {
            scanf("%d",&tb[i]);
        }
        for(i=1;i<=m;i++)//预处理出每个数据包能在的区间
        {
            ve[i].clear();
            int ix=upper_bound(ta+1,ta+n+1,tb[i])-ta;
            ve[i].push_back(ix);
            for(j=ix;j<=n;j++)
            {
                if(ta[j]-tb[i]<d)
                {
                    ve[i].push_back(j+1);
                }
                else
                    break;
            }
            for(j=ix-1;j>=1;j--)
            {
                if(tb[i]-ta[j]<d)
                {
                    ve[i].push_back(j);
                }
                else
                    break;
            }
            sort(ve[i].begin(),ve[i].end());
        }
        LL sum;
        for(i=0;i<(int)ve[1].size();i++)
        {
            dp[1][i]=1;
        }
        for(i=2;i<=m;i++)
        {
            int id=0;
            sum=0;
            for(j=0;j<(int)ve[i].size();j++)
            {
                for(;id<(int)ve[i-1].size();id++)
                {
                    if(ve[i-1][id]>ve[i][j])
                        break;
                    sum=(sum+dp[i-1][id])%mod;
                }
                dp[i][j]=sum;
            }
        }
        LL ans=0;
        for(j=0;j<(int)ve[m].size();j++)
            ans=(ans+dp[m][j])%mod;
        printf("Case #%d: %lld\n",cas++,ans);
    }
    return 0;
}



 

你可能感兴趣的:(dp,动态规划,ACM)