POJ 2609 Ferry Loading
双塔DP+输出路径。
由于内存限制,DP只能开滚动数组来记录。
我的写法比较渣,但是POJ能AC,但是ZOJ依旧MLE,更加奇怪的是Uva上无论怎么改都是WA,其他人POJ过的交到Uva也是WA。
#include<cstdio> #include<cstring> #include<cmath> #include<stack> #include<algorithm> using namespace std; int dp[2][20000+10]; struct P { int x,y; int f; }pre[505][20000+10]; int sum; int a[505],tot; void read() { while(1) { scanf("%d",&a[tot+1]); if(a[tot+1]==0) break; tot++; } for(int i=0;i<=tot;i++) for(int j=0;j<=2*sum;j++) pre[i][j].f=-1; for(int j=0;j<=2*sum;j++) dp[1][j]=dp[0][j]=0x7FFFFFFF; } void init() { sum=sum*100; tot=0; } void work() { int now=0; dp[0][a[1]+sum]=0; pre[1][a[1]+sum].f=0; dp[0][0-a[1]+sum]=0; pre[1][0-a[1]+sum].f=1; for(int i=2;i<=tot;i++) { now=now^1; for(int j=0;j<=2*sum;j++) dp[now][j]=0x7FFFFFFF; for(int j=0;j<=2*sum;j++) { if(dp[now^1][j]==0x7FFFFFFF) continue; int tmp=j-sum; if(tmp>=0) { if(dp[now^1][j]+tmp+a[i]<=sum&&dp[now^1][j]<dp[now][tmp+a[i]+sum]) { dp[now][tmp+a[i]+sum]=dp[now^1][j]; pre[i][tmp+a[i]+sum].x=i-1; pre[i][tmp+a[i]+sum].y=j; pre[i][tmp+a[i]+sum].f=0; } if(max(tmp,a[i])+dp[now^1][j]<=sum&&dp[now^1][j]+min(tmp,a[i])<dp[now][tmp-a[i]+sum]) { dp[now][tmp-a[i]+sum]=dp[now^1][j]+min(tmp,a[i]); pre[i][tmp-a[i]+sum].x=i-1; pre[i][tmp-a[i]+sum].y=j; pre[i][tmp-a[i]+sum].f=1; } } else { tmp=-tmp; if(dp[now^1][j]+tmp+a[i]<=sum&&dp[now^1][j]<dp[now][0-(tmp+a[i])+sum]) { dp[now][0-(tmp+a[i])+sum]=dp[now^1][j]; pre[i][0-(tmp+a[i])+sum].x=i-1; pre[i][0-(tmp+a[i])+sum].y=j; pre[i][0-(tmp+a[i])+sum].f=1; } if(max(tmp,a[i])+dp[now^1][j]<=sum&&dp[now^1][j]+min(tmp,a[i])<dp[now][a[i]-tmp+sum]) { dp[now][a[i]-tmp+sum]=dp[now^1][j]+min(tmp,a[i]); pre[i][a[i]-tmp+sum].x=i-1; pre[i][a[i]-tmp+sum].y=j; pre[i][a[i]-tmp+sum].f=0; } } } } } void output() { bool flag=0; int now_i,now_j; for(int i=tot;i>=1;i--) { for(int j=2*sum;j>=0;j--) { if(pre[i][j].f!=-1) { now_i=i; now_j=j; flag=1; break; } } if(flag) break; } if(flag==0) {printf("0\n");return;} printf("%d\n",now_i); stack<int>S; while(1) { if(pre[now_i][now_j].f==-1) break; S.push(pre[now_i][now_j].f); int newx,newy; newx=pre[now_i][now_j].x; newy=pre[now_i][now_j].y; now_i=newx; now_j=newy; } int k=1; int left=0; int right=0; while(!S.empty()) { if(S.top()==0) { printf("port\n"); left=left+a[k];k++; } else { printf("starboard\n"); right=right+a[k];k++; } S.pop(); } } int main() { scanf("%d",&sum); init(); read(); work(); output(); return 0; }