您的位置:首页 > 编程语言 > C语言/C++

HDOJ1069 猴子和香蕉【DP】

2013-08-02 00:27 513 查看
题目详见http://acm.hdu.edu.cn/showproblem.php?pid=1069
这个题目的大致意思就是香蕉挂在一定的一定的高度,不同的高度都有香蕉。给猴子很N个箱子,有长宽高,让猴子用这些箱子摞在一起爬到高处吃香蕉,看猴子的智商够不够高,吃到的香蕉多不多。箱子可以翻转,但是一个箱子要想摞在其他箱子上边,必须满足长和宽都要小于底下的箱子。箱子的数目是不限的,只是给出不同的箱子种类。每种箱子可以多次使用。
看到这里,想必对此题有了大致的了解了。箱子虽然无限,但是总类有限。所以每一种箱子,最多只能用3次。因为有长宽的限制,所以只能这样。
怎么做呢?
对于输入的箱子我们怎么保存,长宽高可以调换。虽然无限,每种箱子最多只用3次。而且这三次还有重复的。比如 5  5 6 ,那么翻转一下变成 5 5 6 ,5 6 5 ,5 6 5。5 5 5 变成3个 5 5 5 .可以进行重复的处理,可是我这里就没处理,觉得无伤大雅。不过这是不严谨的态度,要向好的复杂度看齐。如果所有的都是正方体,岂不是浪费了2/3的时间和内存啊。不过在这刷题呢就没在乎这么多,先不管了。。以后再实现。存入3N的数据,数据显然要用结构体来处理。


typedef struct Block
{
int width;
int length;
int height;
}Block;


存入数据之后怎么办?
首先要排序,不排序是没法搞的。怎么排序?按面积?长度,高度?在这里我们以长度为主排序,如果长度相同,那么以高度为主。而且这里要处理长和宽,如果长小于宽,要调换的。因为这会影响排序的。比如 1 10 100,长度是1,肯定排到最后了,可是宽是10,高度是100啊。这就很坑里。所以要长宽符合,拍好序。有人说用面积,我觉得应该也可以,或许会更好,可是比较蛮烦一些。这里就用刚才说的处理,排序用的是从大到小,一点一点的往上堆。
排序之后呢?这个题要用动态规划,这个DP和之前的最长递增子序列有点类似。这个DP的每一项和之前的每一个都有关系,不是仅仅是和前一个有关系。定义Height[i]是前i个箱子可以堆成的最大高度。
我们得到的状态转移方程

	Height[i]=MAX{block[i].height,block[i].block+Height[j]} block[i].block+Height[j]>Height[i] 0<=j<=i-1;。对底下的每一个都要判断一下是否可以放在上面,还有比较高度,更新高度。这样才可以可以解决问题。

上代码


#include <iostream>
#include<algorithm>
#include<vector>
using namespace std;

typedef struct Block { int width; int length; int height; }Block;
int MaxBlockHeight(vector<Block> block,int n); //求所有的的箱子堆的最大高度。
int MaxToMin(const Block& a ,const Block& b);//从大到小排序,以长为主,宽为辅
void Adjust(Block &a);//调整宽度和长度的位置
int main()
{
int n;
Block a,b,c; //没每一类处理3个箱子
vector<Block> block;
int i,j;
j=0;
while(cin>>n)
{
if(0==n)
break;
i=n;
block.clear(); //不忘记清零
while(i--)
{
cin>>b.width;
cin>>b.length;
cin>>b.height;
a.width=b.width;
a.length=b.height;
a.height=b.length;
c.width=b.length;
c.length=b.height;
c.height=b.width;
Adjust(a);
Adjust(b);
Adjust(c);
block.push_back(b);
block.push_back(a);
block.push_back(c);
}
//for_each(block.begin(),block.end(),show);
sort(block.begin(),block.end(),MaxToMin);//排序
// for_each(block.begin(),block.end(),show);
cout<<"Case "<<++j<<": maximum height = "<<MaxBlockHeight(block,n)<<endl

}
return 0;
}
//求所有的的箱子堆的最大高度。
int MaxBlockHeight(vector<Block> block,int n)
{
int Max=0; //初始化
int *height=new int[3*n];
int i,j;
for(i=0;i<3*n;i++)
{
height[i]=block[i].height;
for(j=i-1;j>=0;j--)
{
if((block[i].width<block[j].width)&&(block[i].length<block[j].length)&&(block[i].height+height[j]>height[i]))
{
height[i]=block[i].height+height[j];
//break;不可以这么做。
}
}
if(height[i]>Max)
Max=height[i];
}
return Max;
}
//从大到小排序,以长为主,宽为辅
int MaxToMin(const Block& a ,const Block& b)
{
if(a.length>b.length)
return true;
else if(a.length==b.length&&a.width>=b.width)
return true;
else
return false;
}
void Adjust(Block &a)//调整宽度和长度的位置
{
int temp;
if(a.width>a.length)
{
temp=a.width;
a.width=a.length;
a.length=temp;
}
}
OK,很nice的AC了。继续刷题啦啦啦

转载请注明出处http://blog.csdn.net/liangbopirates/article/details/9709113
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM C++ 算法 动态规划