ZOJ 2059 The Twin Towers

本以为自己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;
}


 

你可能感兴趣的:(ZOJ 2059 The Twin Towers)