想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:有n个砖块,每个砖块有长宽高,每个砖块有无限个,问叠起来最高有多高,一个砖块能够放在另一个砖块上的标准是
,上面砖块的长和宽都要小于下面砖块的长和宽
解题思路:类似于最长升序序列的DP,只不过需要变化一下,因为每个砖块无限个,立体的砖块,长和宽也可以作为高,而题目要求小于,
所以每个砖块分为3个不同的砖块,这样我们为了区分,将宽看做大的一边,长看做小的一边,这样就不用分为6个,再将所有砖块按照宽
来升序排序,接着用最长升序序列dp来比较就ok了
/*
Memory 256K
Time 16MS
*/
#include <iostream>
#include <algorithm>
using namespace std;
int max(int a,int b){
return a>b?a:b;
}
int min(int a,int b){
return a<b?a:b;
}
class CBlock{ //砖块类
public:
int x,y,z; //分别代表长宽高
};
class CJob{
private:
int m_nBlockSum;
CBlock *m_block;
public:
int Run();
void AddBlock(int x,int y,int z);
CJob(int x);
~CJob();
};
CJob::CJob(int x){
m_nBlockSum = 0;
m_block = new CBlock[3*x];
}
CJob::~CJob(){
delete m_block;
}
void CJob::AddBlock(int x,int y,int z){
m_block[m_nBlockSum].x = x;
m_block[m_nBlockSum].y = y;
m_block[m_nBlockSum].z = z;
m_nBlockSum++;
}
int cmp(const CBlock &a, const CBlock &b){
return a.x < b.x;
}
int CJob::Run(){
sort(m_block,m_block+m_nBlockSum,cmp); //首先按长按顺时针排序,这样可以保证答案出来是一个最优值
int ans = 0;
int *dp = new int[m_nBlockSum*3];
int i,j;
for(i = m_nBlockSum - 1;i >= 0;i--){ //最长上升序列的dp
dp[i] = m_block[i].z;
for(j = i + 1;j < m_nBlockSum;j++){
if(m_block[j].x > m_block[i].x && m_block[j].y > m_block[i].y){
dp[i] = max(dp[j]+m_block[i].z,dp[i]);
}
}
}
for(i = 0;i < m_nBlockSum;i++){
ans = max(ans,dp[i]);
}
delete dp;
return ans;
}
int main(){
int n,x,y,z,Case = 0;
while(cin>>n){
if(!n) break;
CJob job(n);
while(n--){
cin>>x>>y>>z;
job.AddBlock(min(x,y),max(x,y),z); //这里注意,我们标记小的为长,大的为宽
job.AddBlock(min(y,z),max(y,z),x);
job.AddBlock(min(x,z),max(x,z),y);
}
cout<<"Case "<<++Case<<": maximum height = "<<job.Run()<<endl;
}
return 0;
}