动态规划2-----hdu1069
首先这道题目先要理解题目的意思。
用一些方块堆塔,给出的每种方块个数是无限的,只有满足长宽都小于下面一个方块的方块才能摆上去。
首先这道题需要一个转化。
每个方块有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的更多相关文章
- HDU-1069 Monkey and Banana DAG上的动态规划
题目链接:https://cn.vjudge.net/problem/HDU-1069 题意 给出n种箱子的长宽高 现要搭出最高的箱子塔,使每个箱子的长宽严格小于底下的箱子的长宽,每种箱子数量不限 问 ...
- 增强学习(三)----- MDP的动态规划解法
上一篇我们已经说到了,增强学习的目的就是求解马尔可夫决策过程(MDP)的最优策略,使其在任意初始状态下,都能获得最大的Vπ值.(本文不考虑非马尔可夫环境和不完全可观测马尔可夫决策过程(POMDP)中的 ...
- 简单动态规划-LeetCode198
题目:House Robber You are a professional robber planning to rob houses along a street. Each house has ...
- 动态规划 Dynamic Programming
March 26, 2013 作者:Hawstein 出处:http://hawstein.com/posts/dp-novice-to-advanced.html 声明:本文采用以下协议进行授权: ...
- 动态规划之最长公共子序列(LCS)
转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...
- C#动态规划查找两个字符串最大子串
//动态规划查找两个字符串最大子串 public static string lcs(string word1, string word2) { ...
- C#递归、动态规划计算斐波那契数列
//递归 public static long recurFib(int num) { if (num < 2) ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- 【BZOJ1700】[Usaco2007 Jan]Problem Solving 解题 动态规划
[BZOJ1700][Usaco2007 Jan]Problem Solving 解题 Description 过去的日子里,农夫John的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地 ...
随机推荐
- 使用block函数的基本形式
以前从未接触过block函数. 如果在.h头文件中定义的形式如下的话: @property (nonatomic, copy) void(^fontValueChangedBlock)(void); ...
- #define const extern
将父类中的常量放到. m文件,子类就不会重复包含了.之后再.h文件中用extern NSSting * const ILScoreShowStartTime;// extern 用来声明变量和函数.c ...
- shell小脚本工具合集
1.将指定内容写入文件 echo "hello world" > file.txt echo "hello world" >> file.tx ...
- radiobutton以及checkbox背景图片拉伸变形的问题
设置RadioButton的text属性,只需要有这个属性就可以(设置“”内容就行),然后再添加textsize属性,将字体大小属性值设置为比较小,我设置为2sp.运行后我们会发现图片变形问题不复存在 ...
- 查看使用了那种shell
cat /etc/shells root@OpenWrt:/www/cgi-bin# cat /etc/shells/bin/ash
- sql server基础学习之引号
create table #(code varchar(20),value int)declare @sql varchar(200) set @sql='insert into # select ' ...
- CentOS 7 rsync
CentOS 7 rsync 1)软件简介 Rsync 是一个远程数据同步工具,可通过 LAN/WAN 快速同步多台主机间的文件.Rsync 本来是用以取代rcp 的一个工具,它当前由 Rsync.s ...
- js css优化-- 合并和压缩
在项目框架中,首先要引用很多css和js文件,80%的用户响应时间都是浪费在前端.而这些时间主要又是因为下载图片.样式表.JavaScript脚本.flash等文件造成的.减少这些资源文件的Reque ...
- ListView控件的Insert、Edit和Delete功能第三部分(自我总结)
1.刚开始在第一部分显示数据的时候出现如下错误: 修改: @Page 中的EnableEventValidation="false" 2.点击各个按钮没有反应. 修改:为page_ ...
- SQL中的左连接与右连接有什么区别,点解返回值会不同?(转)
例子,相信你一看就明白,不需要多说 A表(a1,b1,c1) B表(a2,b2) a1 b1 c1 a2 b2 01 数学 95 01 张三 02 语文 90 02 李四 03 英语 80 04 王五 ...