第四十七题 UVA437 巴比伦塔 The Tower of Babylon

116 篇文章 1 订阅
102 篇文章 1 订阅

题目描述

在这里插入图片描述

输入格式

在这里插入图片描述

输出格式

在这里插入图片描述
题意翻译
【题目】
你可能已经听说过巴比伦塔的传说。现在这个传说的许多细节已经被遗忘。所以本着本场比赛的教育性质,我们现在会告诉你整个传说:
巴比伦人有n种长方形方块,每种有无限个,第i种方块的三边边长是xi,yi,zi。对于每一个方块,你可以任意选择一面作为底,这样高就随着确定了。举个例子,同一种方块,可能其中一个是竖着放的,一个是侧着放的,一个是横着放的。
他们想要用堆方块的方式建尽可能高的塔。问题是,只有一个方块的底的两条边严格小于另一个方块的底的两条边,这个方块才能堆在另一个上面。这意味着,一个方块甚至不能堆在一个底的尺寸与它一样的方块的上面。
你的任务是编写一个程序,计算出这个塔可以建出的最高的高度。
【输入】
输入会包含至少一组数据,每组数据的第一行是一个整数n(n<=30),表示方块的种类数。 这组数据接下来的n行,每行有三个整数,表示xi,yi,zi。 输入数据会以0结束。
【输出】
对于每组数据,输出一行,其中包含组号(从1开始)和塔最高的高度。按以下格式: Case : maximum height = __
【输入样例】

1
10 20 30
2
6 8 10
5 5 5
7
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
5
31 41 59
26 53 58
97 93 23
84 62 64
33 83 27
0
【输出样例】

Case 1: maximum height = 40
Case 2: maximum height = 21
Case 3: maximum height = 28
Case 4: maximum height = 342

题目解析:
本题很像DAG上的动态规划,但是不一样的就是每种立方体可有无限多个,f[i]表示以第i种立方体为底时可以达到的最大高度

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define Maxn 92
using namespace std;
int V[Maxn],G[Maxn][Maxn],f[Maxn],n;
struct Cube{ int x,y; } c[Maxn]; 
// V 存储每个立方体的  “高 ”  
inline void Add_Edge(int i,int j){
	if(c[i].x > c[j].x && c[i].y > c[j].y) G[i][j] = 1;
	if(c[i].x > c[j].y && c[i].y > c[j].x) G[i][j] = 1; 
}	

int dp(int i){
	int &ans = f[i];// C++的引用   不懂得百度一下  和下面那个DP函数的写法不一样 但是结果是一样的 
	if(ans > 0) return ans;
	ans = V[i];
	for(int j=1; j<=3*n; j++)
		if(G[i][j]) ans = max(ans,V[i] + dp(j));
	return ans;
}

int DP(int i) {
	if(f[i] > 0) return f[i];
	f[i] = V[i]; 
	for(int j=1; j<=3*n; j++)
		if(G[i][j]) f[i] = max(f[i],V[i] + DP(j));
	return f[i];
}


int main(int argc,char* argv[]) {
	int kase = 0;
	while(scanf("%d",&n) != EOF && n) {
		memset(f,0,sizeof(f));
		memset(G,0,sizeof(G));
		for(int u,v,w,i=0; i<n; i++){
			scanf("%d %d %d",&u,&v,&w);
			c[i * 3 + 1].x = u,c[i * 3 + 1].y = v, V[i * 3 + 1] = w;
			c[i * 3 + 2].x = w,c[i * 3 + 2].y = v, V[i * 3 + 2] = u;
			c[i * 3 + 3].x = u,c[i * 3 + 3].y = w, V[i * 3 + 3] = v;
		}
		for(int i=1; i<=3*n; i++)
			for(int j=1; j<=3*n; j++)
				Add_Edge(i,j);
		for(int i=1; i<=3*n; i++) DP(i);
		int Ans = 0;
		for(int i=1; i<=3*n; i++) Ans = max(Ans,f[i]);
		printf("Case %d: maximum height = %d\n",++kase,Ans);
	} 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值