Monkey and Banana(DP,我尽量详细讲一下)
题目大致意思:
输入n,再输入n组长、宽、高,代表输入n个不同的长方体(或正方体),都有无限供应 ,让你尽可能的往高了堆。要求是在下面的长方体的长和宽都要比放于其上的长方体大。
做题思路:
#define 块 长方体(或正方体)
每一个块最多有六种摆法。
有n个块,你最多有6n种摆法。
然后你会发现撑死只能叠6n块(一种摆法连续叠两个就不合要求)
将这6*n摆法按照长和宽排序(高不管),从小到大排。
然后讲不清开始口胡:
假定dp[i]表示以第i种摆法的块为底形成的最高的高度。
那么状态转移方程为dp[i] = max(dp[1]~dp[i-1]) + i的高
所以为什么不是 dp[i] = dp[i-1] + i的高 呢?
因为以 i-1 为底的块可能并没有
举个极端的栗子来说:
第几种摆法 | 长 | 宽 | 高 |
---|---|---|---|
i+2 | 30 | 20 | 1 |
i+1 | 25 | 20 | 100 |
i | 15 | 10 | 1 |
dp[i+2] = (i+2)的高 + 前 i 种摆法里自己捣鼓(i+2和i+1宽相同不行)= 1 + 一坨
而 dp[i+1] = (i+1)的高 + 前 i 种摆法里自己捣鼓 = 100 + 一坨
意会,意会。。。
上代码
#include<iostream>
#include<algorithm>
using namespace std;
struct rec
{
int l;
int w;
int h;
};
///作为sort函数第三个参数,来进行这里的结构体排序,不会的可以百度搜一下,感觉挺好用
///cmp函数的两行可以这样写 (比较容易看懂)
///if (a.l==b.l && a.w<b.w) return true;
///else if (a.l<b.l) return true;
///else return false;
bool cmp(const rec& a,const rec& b)
{
if (a.l==b.l) return a.w < b.w;
return a.l < b.l;
}
int dp[185];
rec a[185];
int main()
{
std::ios::sync_with_stdio(false);
int n;
int kca=0;
while (cin>>n,n){
int index = 1;
int x,y,z;
int nn=n;
while (nn--){
cin>>x>>y>>z;
a[index].l = x, a[index].w = y, a[index++].h = z;
a[index].l = x, a[index].w = z, a[index++].h = y;
a[index].l = y, a[index].w = x, a[index++].h = z;
a[index].l = y, a[index].w = z, a[index++].h = x;
a[index].l = z, a[index].w = x, a[index++].h = y;
a[index].l = z, a[index].w = y, a[index++].h = x;
}
cout<<"Case "<<++kca<<": maximum height = ";
sort(a,a+index,cmp);
dp[1] = a[1].h;
for (int i=2;i<index;i++){
int max_h=0;
for (int j=1;j<i;j++){
if ( a[j].w<a[i].w && a[j].l<a[i].l )
max_h=max(max_h,dp[j]);
}
dp[i] = a[i].h + max_h;
}
///dp结束,找dp[1~index-1]中的最大值
int ans=0;
for (int i=1;i<index;i++)
ans = max(ans,dp[i]);
cout<<ans<<endl;
}
return 0;
}
谢谢爸爸的观看,点个赞再走好吗。