UVA437 巴比伦塔

题目链接:https://www.luogu.com.cn/problem/UVA437

题目:有n(n≤30)种立方体,每种都有无穷多个。要求选一些立方体摞成一根尽量高的柱子(可以自行选择哪一条边作为高),使得每个立方体的底面长宽分别严格小于它下方立方体的底面长宽。
intput:

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

output:

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

思路:题目表明每增加一个立方体,长宽都会严格减少,这时我们可以用DAG最长路模板套上去,每个立方体都可以分为三个,例如输入a,b,c,分为以a,b,c作高(有人说是6个,但其实是一样的,因为6个里面必定有两个高是一样,并且长*宽的面积相同),在程序中可以直接判断。

所以我们可以设置一个数组,用dp[i]来表示以第i个方块为底,所能达到的最大高度

样例解析:

解释一下第一个样例,可以拓展为{10,20,30},{10,30,20},{30,20,10}3个立方体,第一个立方体作为底时dp[1]=30(很明显啊,因为其他两块不符合条件),以第二个立方体为底时,dp[1]=20,同理。

以第三个立方体为底时,我们发现第一个立方体可以放上去,这个时候我们已经计算出以第一个立方体为底时的最大高度是多少了,这就是动态规划的精髓,避免了重复计算,所以直接返回dp[2]+h3(第三个立方体的高)

 

ps:另外有一个需要注意的地方,题目中说需要长宽分别严格大于上面立方体的长宽,在这个地方卡了很久,因为我直接计算了两个的面积,然后比较,当然是错误的

最后复习一下结构体重载运算符的知识

例如这样一个定义

bool operator > (const node& now) const{}

这两个const有啥用?

在函数后面加上一个const,编译器就不允许operator>修改类的数据成员

const对象执行时不能调用非const函数

里面的表示数据成员不能被修改,外面的表示函数不能修改数据成员

#include<iostream>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<cstdio>
#include<utility>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll; 
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
/*------------------------------------------------------------------------*/
const int maxn=105; 

struct node{
	int x,y,z;
	void init(int a,int b,int c){
		x=a,y=b,c=z;
	}
	bool operator > (const node& now){
		return ((x>now.x&&y>now.y)||(x>now.y&&y>now.x));
		//return x*y>now.x*now.y;
	}
}star[maxn];
int maze[maxn][maxn];
int dp[maxn];
int n;

int Dp(int now){
	
	if(dp[now])return dp[now];
	dp[now]=star[now].z;//取当前节点的高 
	
	for(int j=1;j<=3*n;++j){
			
		if(star[now]>star[j])
		dp[now]=max(dp[now],star[now].z+Dp(j));
		
	}
	
	return dp[now];
}

int main( )
{	
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    //freopen("a.txt","r",stdin);
    //freopen("a.txt","w",stdout);
    int cnt=1;
    while(cin>>n&&n){
    	memset(dp,0,sizeof(dp));
    	memset(maze,0,sizeof(maze));
    	for(int i=1;i<=3*n;i+=3){
    		
    		int a,b,c;
    		cin>>a>>b>>c;
    		
    		star[i].x=a;
    		star[i].y=b;
    		star[i].z=c;
    		
    		star[i+1].x=a;
    		star[i+1].y=c;
    		star[i+1].z=b;
    		
    		star[i+2].x=c;
    		star[i+2].y=b;
    		star[i+2].z=a;
    	}
    	
    	
    	int res=0;
    	
    	for(int i=1;i<=3*n;++i){
    		
    		
    		res=max(res,Dp(i));
    		
    	}
    	
    	cout<<"Case "<<cnt++<<": "<<"maximum height = "<<res<<endl;
    }
    
    
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值