紫书第九章-----动态规划初步(例题9-2 The Tower of Babylon UVA - 437)

本题类似于嵌套矩形问题,笔者受嵌套矩形问题启发,解决了本道题目。把本题中所有矩形种类求出来(3*n),接下来就是嵌套矩形问题了。

/*
【思路分析】
先把长方体的所有种类存储起来,然后用这些长方体进行dp
大指向小则有边,建立图,因为总是严格的大指向小,所以
一定是有向无环图(DAG)。注意一个长方体可能是多种长方
体,比如(10,20,30),分别以10,20,30为高,则有3种长方体。
题目虽说每个长方体都有无限多个,其实最多也只能用3*n个,
因为如果一个被用了,不可能再用和他完全一样的长方体了。
d(i)表示从第i点出发的最长路
d(i)=max{d(j)+rec[i].z | (i,j)∈E}
*/

#include<iostream>
#include<cstring>
using namespace std;

const int maxn=50;//最多只有30个,不妨稍微搞大点

int n;
int d[maxn*3];

typedef struct{
    int x;
    int y;
    int z;//不妨把x,y当成底座,z当成高
}rectangular;

rectangular rec[maxn*3];

int graph[3*maxn][3*maxn];

int dp(int i){
    int &ans=d[i];
    if(ans>0) return ans;//注意本题要用记忆化搜索,直接递归会超时
    ans=rec[i].z;
    for(int j=1;j<=3*n;j++){
        if(graph[i][j]){
            ans=max(ans,dp(j)+rec[i].z);
        }
    }
    return ans;
}

int main()
{
    int kase=0;
    while(cin>>n && n){
        int cnt=0;
        int xx,yy,zz;
        //把n个矩形块搞成3n个矩形块(即使有重复也没事),比如(20,20,20)搞成三个都一样
        //因为在建立图的时候,重复的之间是不会建立边的
        for(int i=1;i<=n;i++){
            cin>>xx>>yy>>zz;
            ++cnt;
            rec[cnt].x=xx;rec[cnt].y=yy;rec[cnt].z=zz;d[cnt]=rec[cnt].z;
            ++cnt;
            rec[cnt].x=zz;rec[cnt].y=yy;rec[cnt].z=xx;
            ++cnt;
            rec[cnt].x=xx;rec[cnt].y=zz;rec[cnt].z=yy;
        }
        //建图
        memset(graph,0,sizeof(graph));
        for(int i=1;i<=3*n;i++){
            for(int j=1;j<=3*n;j++){
                if((rec[i].x<rec[j].x && rec[i].y<rec[j].y) || (rec[i].x<rec[j].y && rec[i].y<rec[j].x)){
                    graph[i][j]=rec[j].z;//i,j之间有边,我们可以把边权重指定为j对应的z值
                }
            }
        }
        //dp
        memset(d,0,sizeof(d));
        int ans=0;
        for(int i=1;i<=3*n;i++){
            ans=max(ans,dp(i));
        }
        cout<<"Case "<<++kase<<": maximum height = "<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ccnuacmhdu/article/details/81182856