DP,注意单组输入,题目的进程无后效性,适合DP,
由于当时没有估计出车子数量,用了滚动数组。
现在来谈下DP状态的表示,
比较容易想到的是DP【i】【j】【k】(现在的车子编号,队列1长度,队列2长度)
明显MLE,其实我们只需要有前两维即可,因为最后一维可以从前面两维推知:k=sum【i】-j;
问题转为存在性问题了,dp【i】【j】=dp【i-1】【j】|dp【i-1】【j-len【i】】(分别为放在队列1,放在队列2)
注意细节处理
详情见代码:
#include<stdio.h> #include<string.h> const int maxn=10007; bool dp[2][maxn];//表示第i辆车时,第一个队列装了J的容量 int pre[501][maxn]; int sum[501]; int q[501]; void output(int ,int ); int main() { int max,i,j,a,ans,nn,c,T; scanf("%d",&T); while(T--) { scanf("%d",&max); nn=1,ans=0,c=0; max*=100; memset(sum,0,sizeof(sum)); while(scanf("%d",&a)&&a) q[nn++]=a; sum[1]=q[1]; for(i=2;i<nn;i++) sum[i]+=sum[i-1]+q[i]; memset(dp,false,sizeof(dp)); memset(pre,-1,sizeof(pre)); dp[0][0]=true; for(i=1;i<nn;i++) { memset(dp[i&1],false,sizeof(dp[i&1])); for(j=max;j>=0;j--)//第一个队列的长度 { if(sum[i-1]-j>max)//第二个队列爆了 break; if(sum[i]-j<=max)//第二个队列还能装得下 { if(j-q[i]>=0) dp[i&1][j]=dp[(i-1)&1][j]|dp[(i-1)&1][j-q[i]]; else dp[i&1][j]=dp[(i-1)&1][j]; if(dp[(i-1)&1][j]) pre[i][j]=0;//表示装在第二个队列 else if(j-q[i]>=0&&dp[(i-1)&1][j-q[i]]) pre[i][j]=1; } else if(j-q[i]>=0) { dp[i&1][j]=dp[(i-1)&1][j-q[i]]; pre[i][j]=1; } if(dp[i&1][j]) { c=j; ans=i; } } if(ans!=i) //如果这一个车子无法被装下,break break; } printf("%d\n",ans); if(ans) output(ans,c); } return 0; } void output(int x,int y) { if(x<=0) return ; if(pre[x][y]==1) { output(x-1,y-q[x]); printf("port\n"); } else if(pre[x][y]==0) { output(x-1,y); printf("starboard\n"); } else if(pre[x][y]==-1) { while(1) puts("S"); } }