现在的位置: 首页 > 综合 > 正文

HDOJ1069 猴子和香蕉【DP】

2013年10月14日 ⁄ 综合 ⁄ 共 2595字 ⁄ 字号 评论关闭
题目详见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

抱歉!评论已关闭.