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;}
- UVALive 3983 Robotruck
- UVALive - 3983 Robotruck DP
- UVALive 3983 Robotruck
- UVALive 3983 Robotruck (单调队列)
- UVALive - 3983 - Robotruck (DP+单调队列)
- 【暑假】[深入动态规划]UVAlive 3983 Robotruck
- UVAlive - 3983—— Robotruck
- LA 3983 Robotruck
- Live Archive 3983 Robotruck
- Robotruck
- Robotruck
- LA 3983 Robotruck / 单调队列
- la 3983 Robotruck 线性dp
- LA 3983 Robotruck(DP)
- LA 3983 - Robotruck 单调队列优化DP
- LA 3983 Robotruck DP+滑动窗口 *
- uva1169 Robotruck
- LA3983 Robotruck
- DSP TMS320C6000基础学习(6)—— gel文件
- Java的的三元运算符
- hdoj1258
- java.net.UnknownHostException
- [iphone]Code Sign error: Provisioning profile XXXX can't be found
- UVALive 3983 Robotruck
- UVA 590 - Always on the run (dp)
- XDU 1010 素数环
- 求数组中的逆序对(来源于剑指名企offer)
- VIJOS P1037 搭建双塔
- iOS extracts: CGAffineTransformInvert
- 不要虚荣心太强,要踏实肯干
- java异常
- C++学习——循环语句(2)