题目链接: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;
}