本以为自己dp功力已经可以了。。。结果刷zoj分类都要题题看题解。。。
我可以给自己找理由说不知道test cases数量而不好确定时间复杂度吗。。。
这道题难在双塔高度不一定是sum/2,
也就是说不一定所有物品都用上。。
所以既然不能维护塔高,可以维护塔的高度差j,顺便记录矮塔的高度dp[j]。
对于相同的高度差来说,矮塔越高当然越好,
比如说1,5和4,8来比较,自然要4,8这组塔。
所以就可以dp维护最大值了。
我推的状态有这么几种:
1 新的材料(高为k)放在低塔上,那么产生的新高度差是abs(j-k),矮塔的高度是min(dp[j]+j,dp[j]+k),
2 新的材料放在高塔上,新的高度差是j+k,矮塔高度是dp[j],
3 新的材料不放。
数据结构是滚动数组。应我聪神批评教育,设置了两个变量g1,g2代表原数组和新数组。
代码:
#include<cstdio> #include<algorithm> using namespaces std; const int X = 2010; int dp[2][X]; int main(){ int i,j,n,m,k,g1,g2; while(scanf("%d",&n),n>=0){ memset(dp,-1,sizeof(dp)); dp[0][0]=0; for(i=0;i<n;i++){ scanf("%d",&k); g1=i&1;g2=i+1&1; memset(dp[g2],-1,sizeof(dp[g2])); for(j=0;j<X;j++) if(dp[g1][j]!=-1){ dp[g2][abs(j-k)]=max(dp[g2][abs(j-k)],min(j,k)+dp[g1][j]); if(j+k<X)dp[g2][j+k]=max(dp[g2][j+k],dp[g1][j]); dp[g2][j]=max(dp[g2][j],dp[g1][j]); } } if(dp[i&1][0]==0||dp[i&1][0]==-1)printf("Sorry\n"); else printf("%d\n",dp[i&1][0]); } return 0; }