HDU1069(DP)

HDU1069(DP)

这道题较为简单,有了前面DP的基础后,拿到这道题,怎么想呢?我现在理解DP问题就是找到一个方法,能把总问题由上到下分解,有点类似学校安排迎新晚会,任务出来了,然后老师交给学生会主席,学生会主席把任务分解成一个个小任务,安排给各个部门,各个部门的部长再细分成更小的任务给部员,到部员的时候任务就变得可实现了,就可以完成,然后把结果反馈给部长,部长再反馈给主席,而DP的重点就是找到一个相同的任务,使得主席安排给部长的和部长安排给部员的任务是一样的。 

面对这道题,先提取出状态,我所提取的是一个箱子的一种摆法(class pos),比如3 4 5 的箱子,就有三种摆法,5 5 10的箱子有两种摆法,然后每种摆法上面可以摆的箱子用UP数组存储,摆的动作用add函数,注意到是UP里包含了所有在this箱子之上的所有箱子,但实际用哪个箱子放在this上面不需要考虑,这就体现出了DP的特点,我只需要安排出任务,而且确定任务在循环中一定能解决即可,不需要关心任务的中间步骤,这样,先循环确定每一个摆法上面可能有的所有情况,然后再计算哪一种最高(heigh())即可。

#include<iostream>
#include<string>
using namespace std;
class pos {//每一种摆法含有数据还有操作,所以抽象出一个类
public:
	int min;
	int max;
	int h;
	int heigh();
	int MaxHeight;
	pos *up[100];//用于确定this箱子上可以有哪些箱子
	int top ;
	void add(pos &a);
	void creat(int a, int b, int c);
};
int pos::heigh() {
	int a = 0;
	for (int i = 1;i <= top;i++) {//利用MaxHeight存储已经计算过的,减少heigh()的使用,减少时间
		if (up[i]->MaxHeight == 0)
			a = (a > up[i]->heigh() ? a : up[i]->heigh());
		else
			a = (a > up[i]->MaxHeight ? a : up[i]->MaxHeight);
	}
	MaxHeight = a + this->h;
	return a + this->h;
}
void pos::add(pos &a) {
	if(a.min<this->min&&a.max<this->max)
		up[++top] = &a;
}
void pos::creat(int a, int b, int c) {
	min = a;max = b;h = c;
	top = 0;
	MaxHeight = 0;
}
int max(int a, int b) {
	return (a >= b ? a : b);
}
int main() {
	int all;
	int cal = 0;
	while (cin >> all) {
		if (all == 0)
			break;
		int p = 0;
		pos head[100];
		int PutWay = 0;
		for (int i = 1;i <= all;i++) {//这个for循环是为了让长宽高小到大排列,方便后面比较
			int x, y, z;
			cin >> x >> y >> z;
			int a, b, c;
			c = max(max(x, y), z);
			if (z == c)
				b = max(x, y);
			else if (c == x)
				b = max(y, z);
			else
				b = max(x, z);
			a = x + y + z - c - b;
			if (a == c) {//不同规格的箱子有不同的摆法
				head[++PutWay].creat(a, b, c);
				continue;
			}
			else if (a == b) {
				head[++PutWay].creat(a, b, c);
				head[++PutWay].creat(a, c, b);
				continue;
			}
			else if (b == c) {
				head[++PutWay].creat(a, b, c);
				head[++PutWay].creat(b, c, a);
				continue;
			}
			else {
				head[++PutWay].creat(a, b, c);
				head[++PutWay].creat(a, c, b);
				head[++PutWay].creat(b, c, a);
			}
			
		}
		for (int i = 1;i <= PutWay;i++)
			for (int j = 1;j <= PutWay;j++) 
				head[i].add(head[j]);//双重循环,在i上对于每一种j都add上去,符合就进up,不符合则不进
		int mmax = -1;
		for (int i = 1;i <= PutWay;i++)
			mmax = max(mmax, head[i].heigh());
		cout << "Case " <<(++cal)<< ": maximum height = " << mmax<< endl;
	}
}

一开始提交几次都是超时,利用MaxHeight优化后才通过,这里想到了之前看到的一篇文章,讲DP的优点,其中一个就是有一些中间数据是重复利用的,像这道题的每个pos的MaxHeight就反复利用,如果用heigh()的话就是大量的递归。

其实感觉DP和递归还有没太搞懂的递推蛮像的,但是中间数据的复用使DP效率能提高一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值