例题9-2 UVA - 437 The Tower of Babylon 巴比伦塔(DGA-DP)(已更新)

大体题意:

给你n种立方体,每种都无限个,要求选择一些立方体使得高度最大,并且满足越靠上的立方体长宽严格小于下面的!每个立方体可以旋转!

输出最大高度!

思路:

可以把立方体的属性存到Node结构体里,因为一个立方体就可以有6种状态,很少,可以手写进Node里。

然后按照面积排序!

最后按照DGA形式 求最长长度!

if (nod[j].x < nod[i].x && nod[j].y < nod[i].y)
dp[i] = max(dp[i],dp[j]+nod[i].z);

意为j 的序列长度 加上i 即可!

==============================

更新于2016.9.28 下午17:46

再次复习了这道题目,竟然改了很久T_T!!

这是一个DAG模型,最多30种长方体,那么总共的状态就有180种!

我们都给每个状态编号,排序 并且去重!

然后n方复杂度 进行枚举建图!

然后直接枚举最长路即可!

详细见代码:

#include 
#include 
#include 
using namespace std;
const int maxn = 200;
struct Node{
    int r,c,h;
    void read(int r_,int c_,int h_){
        r = r_,c = c_,h = h_;
    }
    bool operator < (const Node& rhs) const {
        return r < rhs.r || (r == rhs.r && c < rhs.c ) || (r == rhs.r && c == rhs.c && h < rhs.h);
    }
    bool operator == (const Node& rhs) const {
        return r == rhs.r && c == rhs.c && h == rhs.h;
    }
}p[maxn];
int n,cnt;
bool g[maxn][maxn];
int dp[maxn];
int dfs(int k){
    int& ans = dp[k];
    if (ans != -1)return ans;
    ans = p[k].h;
    for (int i = 0; i < cnt; ++i){
        if (g[k][i])ans = max(dfs(i)+p[k].h,ans);
    }
    return ans;
}
int main(){
    int kase = 0;
    while(scanf("%d",&n) == 1 && n){
        int u,v,w;
        cnt = 0;
        memset(g,0,sizeof g);
        for (int i = 0; i < n; ++i){
            scanf("%d %d %d",&u, &v, &w);
            p[cnt++].read(u,v,w);
            p[cnt++].read(u,w,v);
            p[cnt++].read(v,w,u);
            p[cnt++].read(v,u,w);
            p[cnt++].read(w,v,u);
            p[cnt++].read(w,u,v);
        }
        sort(p,p+cnt);
        cnt = unique(p,p+cnt) - p;
        for (int i = 0; i < cnt; ++i){
            for (int j = 0; j < cnt; ++j){
                if (p[i].r > p[j].r && p[i].c > p[j].c)
                    g[i][j] = 1;
            }
        }
        int ans = 0;
        for (int i = 0; i < cnt; ++i){
            memset(dp,-1,sizeof dp);
            ans = max(ans,dfs(i));
        }
        printf("Case %d: maximum height = %d\n",++kase,ans);
    }
    return 0;
}



===============================================


#include
#include
#include
using namespace std;
const int maxn = 500 + 10;
struct Node{
	int x,y,z;
	Node ():x(0),y(0),z(0){}
	Node (int x,int y,int z):x(x),y(y),z(z){}
	bool operator < (const Node & rhs) const {
		return x*y < rhs.x*rhs.y;
	}
}nod[maxn];
int dp[maxn];
int main(){
	int n,kase=0;
	while(scanf("%d",&n) == 1 && n){
		memset(dp,0,sizeof dp);
		int cnt = 0;
		for (int i = 0; i < n; ++i){
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			nod[cnt++] = Node(x,y,z);
			nod[cnt++] = Node(x,z,y);
			nod[cnt++] = Node(y,x,z);
			nod[cnt++] = Node(y,z,x);
			nod[cnt++] = Node(z,x,y);
			nod[cnt++] = Node(z,y,x);
		}
		sort(nod,nod+cnt);
		int temp = 0;
		for (int i = 0; i < cnt; ++i){
			dp[i] = nod[i].z;
			for (int j = 0; j < i; ++j){
				if (nod[j].x < nod[i].x && nod[j].y < nod[i].y)
					dp[i] = max(dp[i],dp[j]+nod[i].z);
			}
			temp = max(temp,dp[i]);
		}
		printf("Case %d: maximum height = %d\n",++kase,temp);
	}
	return 0;
}


你可能感兴趣的:(DP,第九章,动态规划初步(例题))