标签:
一道DP题目,一开始题目不是很好想,每一块砖都有三种状态,使用的数量不限。事实上,每一种砖的每一种状态若选择啦则只能用一次,因为题目要求的长方体的长和宽都分别严格递增(递减),所以每一种状态的砖最多只可以用一次,于是将输入的每一块砖通过3种状态存为3块砖,问题转化成啦对在3*n块砖中选择不同的转来使得累加的高度最大。设用类对象S[i]表示第i块砖,先对每一块砖进行调整,长宽高为x,y,z,满足y<x。对砖安x递增的顺序进行排序,若x相等则按照y的递增顺序排。其实最后问题转化成了求一组数中的最大升序和的问题,我们用height[i]表示最后一块选择的是第i块砖条件下的最大高度,于是得到状态转移方程:
height[i]=max{S[i]+height[j]}(S[j]<S[i],0<j<i),S[j]<S[i]表示第j块砖可以排在第i块砖的上面。
#include<iostream>
#include<algorithm>
using namespace std;
#define max 200
class Stone{
public:
int x, y, z;
bool operator<(Stone&a){ //小于号表示严格递增
if (x < a.x&&y < a.y)
return true;
return false;
}
};
int Min(int a, int b){
if (a>b)
return b;
return a;
}
int Max(int a, int b){
if (a > b)
return a;
return b;
}
bool Cmp(Stone&a, Stone&b){
if (a.x < b.x)
return true;
if (a.x == b.x)
return a.y <b.y;
return false;
}
int main(){
Stone S[max];
int height[max];
int a, b, c, i,j, n,T=0;
while (cin >> n&&n){
i = 1;
T++;
while (n--){
cin >> a >> b >> c;
S[i].x = Max(a, b), S[i].y = Min(a, b), S[i].z = c; i++;
S[i].x = Max(b, c), S[i].y = Min(b, c), S[i].z = a; i++;
S[i].x = Max(a, c), S[i].y = Min(a, c), S[i].z = b; i++;
}
n = i-1;
sort(S + 1, S +n+1, Cmp); //按非递减排序
height[0] = 0,height[1] = S[1].z; //初始值
for (i =2; i <=n; i++){
height[i] = S[i].z;
for (j = 1; j < i; j++){
if (S[j]<S[i] && S[i].z + height[j]>height[i])
height[i] = S[i].z + height[j];
}
}
int Max = height[1];
for (i = 2; i <= n;i++) //找到height[i]中的最大值就是要求的值
if (Max < height[i])
Max = height[i];
cout << "Case " << T << ": maximum height = " << Max << endl;
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/td15980891505/p/4980910.html