437 - The Tower of Babylon(记录结果再利用DP)

最近准备进入动态规划的章节,仔细看了看紫书上对01背包的讲解,感觉很好。。之前看《挑战程序设计竞赛》那本书,就没有讲的那么深刻 。      更加深刻的理解了什么叫记录结果再利用,手工操作了一遍01背包的过程,也有点明白它的状态是如何转移的了,而且那个状态方程所构成的递推关系真的很巧妙 。

言归正传。。这道题就是嵌套矩形问题稍微改了一下,之前的嵌套矩形只需要维护一个状态量就行了,但是这道题是立方体,可以翻转的,所以还要维护一个特征量--高。

由于矩形的嵌套关系,每个状态只会出现一次,所以这么表示是完全可以的(和完全背包不同) 。

细节见代码:

#include<bits/stdc++.h>
using namespace std;
int n,d[35][10],Case = 0;
struct node{
    int v[5];
}a[35];
int dp(int i,int k) {
    int& ans = d[i][k];
    if(ans!=-1) return ans;
    ans = 0;
    for(int j=1;j<=n;j++) {
        if(k==0) { //不要被吓到。。这三部分只有很小的不同,复制就行了
            if((a[j].v[0]>a[i].v[1]&&a[j].v[1]>a[i].v[2])||(a[j].v[1]>a[i].v[1]&&a[j].v[0]>a[i].v[2]))
                ans = max(ans,dp(j,2)+a[j].v[2]);
            if((a[j].v[0]>a[i].v[1]&&a[j].v[2]>a[i].v[2])||(a[j].v[2]>a[i].v[1]&&a[j].v[0]>a[i].v[2]))
                ans = max(ans,dp(j,1)+a[j].v[1]);
            if((a[j].v[1]>a[i].v[1]&&a[j].v[2]>a[i].v[2])||(a[j].v[2]>a[i].v[1]&&a[j].v[1]>a[i].v[2]))
                ans = max(ans,dp(j,0)+a[j].v[0]);
        }
        else if(k==1) {
            if((a[j].v[0]>a[i].v[0]&&a[j].v[1]>a[i].v[2])||(a[j].v[1]>a[i].v[0]&&a[j].v[0]>a[i].v[2]))
                ans = max(ans,dp(j,2)+a[j].v[2]);
            if((a[j].v[0]>a[i].v[0]&&a[j].v[2]>a[i].v[2])||(a[j].v[2]>a[i].v[0]&&a[j].v[0]>a[i].v[2]))
                ans = max(ans,dp(j,1)+a[j].v[1]);
            if((a[j].v[1]>a[i].v[0]&&a[j].v[2]>a[i].v[2])||(a[j].v[2]>a[i].v[0]&&a[j].v[1]>a[i].v[2]))
                ans = max(ans,dp(j,0)+a[j].v[0]);
        }
        else {
            if((a[j].v[0]>a[i].v[0]&&a[j].v[1]>a[i].v[1])||(a[j].v[1]>a[i].v[0]&&a[j].v[0]>a[i].v[1]))
                ans = max(ans,dp(j,2)+a[j].v[2]);
            if((a[j].v[0]>a[i].v[0]&&a[j].v[2]>a[i].v[1])||(a[j].v[2]>a[i].v[0]&&a[j].v[0]>a[i].v[1]))
                ans = max(ans,dp(j,1)+a[j].v[1]);
            if((a[j].v[1]>a[i].v[0]&&a[j].v[2]>a[i].v[1])||(a[j].v[2]>a[i].v[0]&&a[j].v[1]>a[i].v[1]))
                ans = max(ans,dp(j,0)+a[j].v[0]);
        }
    }
    return ans;
}
int main() {
    while(~scanf("%d",&n)&&n) {
        for(int i=1;i<=n;i++) scanf("%d%d%d",&a[i].v[0],&a[i].v[1],&a[i].v[2]);
        int ans = -1;
        for(int i=1;i<=n;i++) {
            for(int j=0;j<=2;j++) {
                memset(d,-1,sizeof(d));//每次都要清空,因为每一次的起点不同,导致结果大不一样
                ans = max(ans,dp(i,j)+a[i].v[j]);
            }
        }
        printf("Case %d: maximum height = %d\n",++Case,ans);
    }
    return 0;
}


你可能感兴趣的:(ACM,uva)