首先这道题目先要理解题目的意思。

用一些方块堆塔,给出的每种方块个数是无限的,只有满足长宽都小于下面一个方块的方块才能摆上去。

首先这道题需要一个转化。

每个方块有3个不同的面,每个面长宽交换,一共每个方块最多有6种情况。

X Y Z

1 2 3

2 1 3

3 1 2

1 3 2

2 3 1

3 2 1

如果长宽高有相同的部分还可以减少一些情况

然后对面积,长,宽,从小到大排序。

这步做完dp的准备才算完成。

下面分析dp部分。

如果不用dp,用贪心先试试,先把最大的面积放在下面,然后循环面积比他小的,如果满足长宽都小就摆上去,循环一遍摆完为止。

for(n->1)

{

for(n-1->1)

{

max +=z;

}

}

看上去貌似是可以的,但是其实是不行的,因为你摆了n-1之后,能不能摆n-3了,如果不能,你就不知道n-3和n-4的组合是不是比摆n-1要好了,所以贪心失败。

dp试试

从小到大,先摆最小的,然后用下一个,循环比所有他小的(之前已经摆好了),其中dp【】数据最优的,保存在当前dp【】数组中并且加上当前的方块高度。

状态转移方程

dp【now】 = max(for(now->1)循环中dp【】值最大的) + bolck【now】;

初始值

全部为0

下面给出dp的代码和贪心的代码

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm> using namespace std;
/*dp,hdu1069*/ int dp[];//动态规划的数组 struct block
{
int x;//长
int y;//宽
int z;//高
int s;//面积
}; int cmp(const void * a, const void * b)
{
struct block * p2 = (struct block *)a;
struct block * p1 = (struct block *)b; if(p1->s != p2->s)
return p2->s - p1->s;
else if(p1->x != p2->x)
return p2->x - p1->x;
else
return p2->y - p1->y;
} int main()
{
int n;//方块个数
int i,j;//循环变量
int number=;//记录可行方块数,一个方块最多有6钟可行方案
int maxNumber=;//记录结果
int reslut=;//记录次数
int x,y,z;//用户输入
int tempMax,tempX,tempY;//临时变量 struct block blocks[];//保存所有情况方块
while (true)
{
cin>>n;
if(n==)
break; number=;
for (i = ; i < n; i++)
{
cin>>x>>y>>z; //记录6钟情况
if(x==y&&y==z)
{
blocks[number].x = x;
blocks[number].y = y;
blocks[number].z = z;
blocks[number].s = x*y;
number++;
}
else
{
if(x==y)
{
blocks[number].x = x;
blocks[number].y = y;
blocks[number].z = z;
blocks[number].s = x*y;
number++;
}
else
{
blocks[number].x = x;
blocks[number].y = y;
blocks[number].z = z;
blocks[number].s = x*y;
number++; blocks[number].x = y;
blocks[number].y = x;
blocks[number].z = z;
blocks[number].s = x*y;
number++;
} if(x==z)
{
blocks[number].x = x;
blocks[number].y = z;
blocks[number].z = y;
blocks[number].s = x*z;
number++;
}
else
{
blocks[number].x = x;
blocks[number].y = z;
blocks[number].z = y;
blocks[number].s = x*z;
number++; blocks[number].x = z;
blocks[number].y = x;
blocks[number].z = y;
blocks[number].s = x*z;
number++;
} if(y==z)
{
blocks[number].x = z;
blocks[number].y = y;
blocks[number].z = x;
blocks[number].s = y*z;
number++;
}
else
{
blocks[number].x = z;
blocks[number].y = y;
blocks[number].z = x;
blocks[number].s = y*z;
number++; blocks[number].x = y;
blocks[number].y = z;
blocks[number].z = x;
blocks[number].s = y*z;
number++;
}
}
} //对于s-x-y小到大排序所有方块
qsort(blocks, number, sizeof(block), cmp); maxNumber = ;
tempMax=;
dp[] = blocks[].z;
maxNumber = dp[];
for (i = ; i < number; i++)
{
dp[i]=blocks[i].z;
tempMax=;
tempX=blocks[i].x;
tempY=blocks[i].y; for (j = i-; j >= ; j--)
{
if(tempX > blocks[j].x && tempY > blocks[j].y)
{
if(tempMax < dp[j])
tempMax=dp[j];
}
} dp[i] += tempMax;
if(dp[i] > maxNumber)
maxNumber=dp[i];
} printf("Case %d: maximum height = %d\n",reslut,maxNumber);
reslut++;
}
return ;
}

贪心

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm> using namespace std;
/*贪心,失败,hdu1069*/ struct block
{
int x;//长
int y;//宽
int z;//高
int s;//面积
}; int cmp(const void * a, const void * b)
{
struct block * p1 = (struct block *)a;
struct block * p2 = (struct block *)b; if(p1->s != p2->s)
return p2->s - p1->s;
else if(p1->x != p2->x)
return p2->x - p1->x;
else
return p2->y - p1->y;
} int main()
{
int n;//方块个数
int i,j;//循环变量
int number=;//记录可行方块数,一个方块最多有6钟可行方案
int maxNumber=;//记录结果
int reslut=;//记录次数
int x,y,z;//用户输入
int tempMax,tempX,tempY; struct block blocks[];
while (true)
{
cin>>n;
if(n==)
break; number=;
for (i = ; i < n; i++)
{
cin>>x>>y>>z; //记录6钟情况
if(x==y&&y==z)
{
blocks[number].x = x;
blocks[number].y = y;
blocks[number].z = z;
blocks[number].s = x*y;
number++;
}
else
{
if(x==y)
{
blocks[number].x = x;
blocks[number].y = y;
blocks[number].z = z;
blocks[number].s = x*y;
number++;
}
else
{
blocks[number].x = x;
blocks[number].y = y;
blocks[number].z = z;
blocks[number].s = x*y;
number++; blocks[number].x = y;
blocks[number].y = x;
blocks[number].z = z;
blocks[number].s = x*y;
number++;
} if(x==z)
{
blocks[number].x = x;
blocks[number].y = z;
blocks[number].z = y;
blocks[number].s = x*z;
number++;
}
else
{
blocks[number].x = x;
blocks[number].y = z;
blocks[number].z = y;
blocks[number].s = x*z;
number++; blocks[number].x = z;
blocks[number].y = x;
blocks[number].z = y;
blocks[number].s = x*z;
number++;
} if(y==z)
{
blocks[number].x = z;
blocks[number].y = y;
blocks[number].z = x;
blocks[number].s = y*z;
number++;
}
else
{
blocks[number].x = z;
blocks[number].y = y;
blocks[number].z = x;
blocks[number].s = y*z;
number++; blocks[number].x = y;
blocks[number].y = z;
blocks[number].z = x;
blocks[number].s = y*z;
number++;
}
}
} qsort(blocks, number, sizeof(block), cmp); maxNumber = ;
tempMax=;
tempX=;
tempY=;
for (i = ; i < number; i++)
{
tempMax=blocks[i].z;
tempX=blocks[i].x;
tempY=blocks[i].y;
for (j = i+; j < number; j++)
{
if(tempX > blocks[j].x && tempY > blocks[j].y)
{
tempX=blocks[j].x;
tempY=blocks[j].y;
tempMax += blocks[j].z;
}
}
if(tempMax > maxNumber)
maxNumber=tempMax;
} printf("Case %d: maximum height = %d\n",reslut,maxNumber);
reslut++;
}
return ;
}

经过实践,贪心可以满足前几组数据,但是最后一组数据就GG了

而且贪心和dp的效率在这里均为O(NlogN + N!)所以并没有快。

再一次证明dp确实很多时候比贪心好用。

但是其实最重要的是在dp之前对题目的分析,要把一个题目抽象到一组数,这个才是需要特别去考虑的事情,如果之前都想不到的话是肯定得不到最后的答案的。

动态规划2-----hdu1069的更多相关文章

  1. HDU-1069 Monkey and Banana DAG上的动态规划

    题目链接:https://cn.vjudge.net/problem/HDU-1069 题意 给出n种箱子的长宽高 现要搭出最高的箱子塔,使每个箱子的长宽严格小于底下的箱子的长宽,每种箱子数量不限 问 ...

  2. 增强学习(三)----- MDP的动态规划解法

    上一篇我们已经说到了,增强学习的目的就是求解马尔可夫决策过程(MDP)的最优策略,使其在任意初始状态下,都能获得最大的Vπ值.(本文不考虑非马尔可夫环境和不完全可观测马尔可夫决策过程(POMDP)中的 ...

  3. 简单动态规划-LeetCode198

    题目:House Robber You are a professional robber planning to rob houses along a street. Each house has ...

  4. 动态规划 Dynamic Programming

    March 26, 2013 作者:Hawstein 出处:http://hawstein.com/posts/dp-novice-to-advanced.html 声明:本文采用以下协议进行授权: ...

  5. 动态规划之最长公共子序列(LCS)

    转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...

  6. C#动态规划查找两个字符串最大子串

     //动态规划查找两个字符串最大子串         public static string lcs(string word1, string word2)         {            ...

  7. C#递归、动态规划计算斐波那契数列

    //递归         public static long recurFib(int num)         {             if (num < 2)              ...

  8. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  9. 【BZOJ1700】[Usaco2007 Jan]Problem Solving 解题 动态规划

    [BZOJ1700][Usaco2007 Jan]Problem Solving 解题 Description 过去的日子里,农夫John的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地 ...

随机推荐

  1. js继承实现

    JS实现继承可以分为:对象冒充和原型链继承 其中对象冒充又包括:临时变量,call 和 apply 临时变量方法: function Person(name,sex){ this.name = nam ...

  2. ValueStack背后的OGNL表达式

    原文地址:http://blog.csdn.net/li_tengfei/archive/2010/12/25/6098134.aspx 前言: Strut2的Action类通过属性可以获得所有相关的 ...

  3. dialog弹出,点击back按键无法返回问题解决

    今天阅读队友代码,调试代码中,发现对话框弹出点击back按键无法返回问题解决. 代码如下: /** * 单个按钮没有标题的弹框 * * @param context * @param content内 ...

  4. python 自动认证登录

    import urllib import base64 import urllib2 def auto_login(urllink,username,password): authstr = 'Bas ...

  5. Xbox360自制系统GOD包安装教程

    1.准备工作 U盘或移动硬盘一个,已下载好的GOD包,本教程用一个32G的U盘和游戏<猎天使魔女>为例. 右击U盘,属性,查看你的U盘是否为FAT32格式. 如果是FAT32格式,则可直接 ...

  6. 句柄C++

    C++中的句柄 这个句柄只是从英文handle翻译过来的,只问句是什么意思难以解释,这个是我从别人的空间收集的信息, 功能上的理解: 什么是"句柄"(handle),handle的 ...

  7. Servlet基础知识

    基本知识一.Web结构1.两种应用程序 ①桌面应用程序:QQ.CS.MyEclipse.Office.DW.360.浏览器等必须下载.安装.桌面快捷方式.注册表信息.操作系统后台服务.占用操作系统端口 ...

  8. DDE复盘流程

    开始复盘: 1 导入前面数据 重新复盘: 1.打开行情管理器 2.关闭图表 3.删除tick和1分钟图 4.关闭行情管理器 5.开启.

  9. oc汉子转拼音

    oc中可以不使用第三方库直接吧数组转成拼音: 代码如下: NSString *str = @"中国abc人民共和国"; CFStringRef aCFString=(__bridg ...

  10. 算法:1!+(1!+3!)+(1!+3!+5!) + ( 1! + 3! + 5! + 7! + 9!)+....+(1!+3!+5!+ ... + m!)

    -(void)touchesBegan:(nonnull NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event{ / ...