动态规划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的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地 ...
随机推荐
- 快速破解ps方法
1.首先现在ps安装包和破解包. 2.运行Block Adobe Activation,防止ADOBE激活程序启动,按操作提示即可. 3.运行Adobe CS6安装程序. 4.选择“试用”. 5.输入 ...
- HDU 5755 Gambler Bo
可以设n*m个未知量,建立n*m个方程.位置i,j可以建立方程 (2*x[i*m+j]+x[(i-1)*m+j]+x[(i+1)*m+j]+x[i*m+j-1]+x[i*m+j+1])%3=3-b[i ...
- python 自动认证登录
import urllib import base64 import urllib2 def auto_login(urllink,username,password): authstr = 'Bas ...
- php给数组key:value中的key加引号
public function Ext_json_decode($str, $mode=false){ if(preg_match('/\w:/', $str)){ $str = preg_repla ...
- pudn下载地址的规律
A:http://download.pudn.com/downloads15/sourcecode/app/354278Cams.rar(随机数字6个)B:http://www.pudn.com/do ...
- Entity Framework技巧系列之一 - Tip 1 - 5
提示1. 在Entity Framework中怎样排序关系(Relationships) 问题: 在Entity Framework论坛中常会看到关于排序相关联项目的问题. 例如,想象你要查询客户,并 ...
- JqGrid动态改变列名
setLabel colname, data, class, properties jqGrid对象 给指定列设置一个新的显示名称.colname:列名称,也可以是列的位置索引,从0开始:data:列 ...
- android动态LinearLayout
在onCreate函数中: mLinearlayout= new LinearLayout(this); mLinearlayout.setOrientation(LinearLayout.VERTI ...
- Hadoop2.6.0 动态增加节点
本文主要从基础准备,添加DataNode和添加NodeManager三个部分详细说明在Hadoop2.6.0环境下,如何动态新增节点到集群中. 基础准备 在基础准备部分,主要是设置hadoop运行的系 ...
- .Net下HTTP访问穿越多层代理的方法以及代理服务器的验证 转载
https://blog.williamgates.net/2006/07/aspdotnet-through-multi-proxy/ 首先,通过普通的匿名透明代理的方法,是直接使用Socket发送 ...