poj2241 - The Tower of Babylon

15 篇文章 0 订阅

                                想看更多的解题报告: 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;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值