UVALive 3983 Robotruck

来源:互联网 发布:cad服装制图软件 编辑:程序博客网 时间:2024/06/03 21:39

题目大意:有一个机器人要去送邮件,n个邮件,按照一定顺序来,机器人有一定的容量C,它可以顺序拿重量不超过C的邮件拿去送,然后,回来再拿再送,送完为止,注意,送的时也要按照拿的顺序送,给你每个邮件要送达的坐标,(0,0)为它拿邮件的地方,问你送完邮件机器人最少需要走的曼哈顿距离。

思路:很清楚,就是动态规划。d[ i ]表示送完i件,所需走过的最短距离。那么d[ i ] = min(d[ j ] + dis(j+1 ,0)+dis(j+1,i)+dis( i ,0),其中w[ j +1 ] + w[j+2] +……w[ i ] < =C) 。

因为C只有100,一开始我就写了个O(nC)的,先开始因为没看到送的时候也要按照顺序送、距离算成最短了而WA了两次,然后看到后,马上AC了。然后又看了书上写的,发现他的基本思想和我一样,但是他还做了优化,它维护了一个滑动区间,用s[ i ]表示从1到2,2到3……到i走过的距离,dis[ i ] 就只表示i到起始位置的距离,那么上述表达式可以写为d[ i ] = min ( d[ j ] + dis[ j+1 ] - sum[ j+1 ]) + dis[ i ] + sum[ i ] ,当然w和<=C。我们所要找的就是满足w条件的 d[ j ] + dis[ j+1 ] - sum[ j+1 ] 的最小值,他是一段区间,称为滑动区间。我们把这些区间里的元素看成一个队列,让它从小到大排列,每次删掉队头w不满足条件的元素,然后用队头直接更新d[ i ] ,删掉队尾比新加的元素对应的值还要大的元素,这样就维护了这个递增队列。由于每个元素最多进队列一次,总的复杂度为O(n)。

优化后的代码如下:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int INF = 0x0fffffff ;const int MAXN = 111111 ;struct Pack{    int x,y;    int w;    Pack(){}    Pack(int a,int b,int c) : x(a),y(b),w(c){}} pack[MAXN];int d[MAXN];int sum[MAXN],tot_w[MAXN];int cal_dis(int x){    return (pack[x].x+pack[x].y);}int func(int x){    return d[x]+cal_dis(x+1)-sum[x+1];}int q[MAXN];int main(){    int T;    scanf("%d",&T);    while(T--)    {        int c,n;        scanf("%d%d",&c,&n);        int x1,y1,w1;        sum[0]=0;        pack[0] = Pack(0,0,0);        tot_w[0] = 0;        for(int i = 1;i<=n;i++)        {            scanf("%d%d%d",&x1,&y1,&w1);            pack[i] = Pack(x1,y1,w1);            sum[i] = sum[i-1] + abs(pack[i].x-pack[i-1].x)+abs(pack[i].y-pack[i-1].y);            tot_w[i] = tot_w[i-1]+w1;        }        int front=0,rear=0;        q[0] =0 ;        for(int i = 1;i<=n;i++)        {            while(front<=rear&&tot_w[i]-tot_w[q[front]]>c) front++;            d[i] = func(q[front])+cal_dis(i)+sum[i];            while(front<=rear&&func(i)<=func(q[rear])) rear--;            q[++rear] = i;        }        printf("%d\n",d[n]);        if(T) puts("");    }    return 0;}


下面是我自己写的没有优化的代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int INF = 0x0fffffff ;const int MAXN = 111111 ;struct Pack{    int x,y;    int w;    Pack(){}    Pack(int a,int b,int c) : x(a),y(b),w(c){}} pack[MAXN];int d[MAXN];int sum[MAXN];int main(){    int T;    scanf("%d",&T);    while(T--)    {        int c,n;        scanf("%d%d",&c,&n);        int x1,y1,w1;        sum[0]=0;        pack[0] = Pack(0,0,0);        for(int i = 1;i<=n;i++)        {            scanf("%d%d%d",&x1,&y1,&w1);            pack[i] = Pack(x1,y1,w1);            sum[i] = sum[i-1] + abs(pack[i].x-pack[i-1].x)+abs(pack[i].y-pack[i-1].y);        }        for(int i = 1;i<=n;i++)            d[i] = INF;        d[0]=0;        for(int i = 0;i<n;i++)        {            int w = 0;            for(int j = i+1;j<=n;j++)            {                w += pack[j].w;                if(w>c) break;                d[j] = min(d[j],d[i]+sum[j]-sum[i+1]+(pack[i+1].x+pack[i+1].y)+(pack[j].x+pack[j].y));            }        }        printf("%d\n",d[n]);        if(T) puts("");    }    return 0;}


原创粉丝点击