动态规划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的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地 ...
随机推荐
- 10个男孩和n个女孩共买了n2+8n+2本书,已知他们每人买的书本的数量是相同的,且女孩人数多于南海人数,问女孩人数是多少?(整除原理1.1.3)
10个男孩和n个女孩共买了n2+8n+2本书,已知他们每人买的书本的数量是相同的,且女孩人数多于南海人数,问女孩人数是多少? 解: 因为,每个人买的书本的数量是相同的, 所以,10|n2+8n+2 所 ...
- ural 1013. K-based Numbers. Version 3(动态规划)
1013. K-based Numbers. Version 3 Let’s consider K-based numbers, containing exactly N digits. We def ...
- div盒子水平垂直居中的方法
这个问题比较老,方法比较多,各有优劣,着情使用. 一.盒子没有固定的宽和高 方案1.Transforms 变形 这是最简单的方法,不仅能实现绝对居中同样的效果,也支持联合可变高度方式使用.内容块定义t ...
- 在鼠标右键添加“使用WPS打开”
假设WPS安装在 “D:\Program Files\Kingsoft\WPS Office” 目录下,导入以下注册表内容: Windows Registry Editor Version 5.00 ...
- jail brak 获取当前安装app列表
ios 5 6 7 可以通过解析"/private/var/mobile/Library/Caches/com.app.mobile.installation.plist" 文件获 ...
- 不自动切换eclipse视图
刚开始使用eclipse进行调试时,当弹出"Confir Perspective Switch"视图时,不小心点了“No”.以后每次debug的时候都不切换到debug视图. 后发 ...
- UVALive 7070 The E-pang Palace(暴力)
实话说这个题就是个暴力,但是有坑,第一次我以为相含是不行的,结果WA,我加上相含以后还WA,我居然把这两个矩形的面积加在一块了吗,应该取大的那一个啊-- 方法就是枚举对角线,为了让自己不蒙圈,我写了一 ...
- Astyle编程语言格式化工具的说明
1.工具->扩展和更新,搜astyle插件,下载安装重启,当前是2.0版本. 2.工具->选项->AStyle Formatter->Edit,填入下面的,点击save,确定. ...
- mipi 调试经验(转)
以下是最近几个月在调试 MIPI DSI / CSI 的一些经验总结,因为协议有专门的文档,所以这里就记录一些常用知识点: 一.D-PHY 1.传输模式 LP(Low-Power) 模式:用于传输控制 ...
- 【Machine Learning in Action --2】K-最近邻分类
1.K-近邻算法(KNN)概述 K-近邻算法采用测量不同特征值之间的距离方法进行分类. 工作原理:存在一个样本数据集合(也称作训练样本集),并且样本集中每个数据都存在标签(即我们知道样本集中每一数据与 ...