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