小白进阶之动态规划-钢条切割
2016-06-27 18:47
183 查看
关于动态规划算法,首先是:
什么样子的问题适合用动态规划算法来解呢?
适合用动态规划算法解的问题应具有两个性质:最优子结构性质和具有重复子问题
最优子结构性质是指:若一个问题的最优解包含其子问题的最优解,则此问题具有最优子结构性质。
具有重复子问题性质是指:问题的递归算法会反复求解相同的子问题。
然后是:
动态规划算法的设计有四个步骤:
1.刻画一个最优解的结构特征-寻找最优子结构;
2.递归地定义最优解的值;
3.计算最优解的值,通常采用自底向上的方法;
4.利用计算出的信息构造一个最优解。
动态规划算法有4个经典问题:钢条切割、矩阵链乘法、最长公共子序列、最优二叉搜索树。
本文会解决钢条切割问题,其他问题会后面的文章中解决。
钢条切割
给定一段长度为n英寸的钢条和一个价格表,求切割钢条的方案,使受益最大。
求解方法:将钢条从左边切下长度为i的一段,只对右边剩下的长度为n-i的一段继续切。
价格表如下:
动态规划求解有两种方法:带备忘的自顶向下法和自底向上法,期望运行时间都为:θ(n²)。
(1)带备忘的自顶向下法:按照递归形式编写过程,但过程中会保存每一个子问题的解。当需要一个子问题的解时,过程首先检查是否已经保存过此解,若是则返回保存的值。
(2)自底向上法:当求解其子问题时,它所依赖的那些更小的子问题都已经求解完毕并且结果已经保存。
下面就贴程序源码了:
rodCutting.h:
rodCutting.cpp
main.cpp:
什么样子的问题适合用动态规划算法来解呢?
适合用动态规划算法解的问题应具有两个性质:最优子结构性质和具有重复子问题
最优子结构性质是指:若一个问题的最优解包含其子问题的最优解,则此问题具有最优子结构性质。
具有重复子问题性质是指:问题的递归算法会反复求解相同的子问题。
然后是:
动态规划算法的设计有四个步骤:
1.刻画一个最优解的结构特征-寻找最优子结构;
2.递归地定义最优解的值;
3.计算最优解的值,通常采用自底向上的方法;
4.利用计算出的信息构造一个最优解。
动态规划算法有4个经典问题:钢条切割、矩阵链乘法、最长公共子序列、最优二叉搜索树。
本文会解决钢条切割问题,其他问题会后面的文章中解决。
钢条切割
给定一段长度为n英寸的钢条和一个价格表,求切割钢条的方案,使受益最大。
求解方法:将钢条从左边切下长度为i的一段,只对右边剩下的长度为n-i的一段继续切。
价格表如下:
长度i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
价格p[i] | 1 | 5 | 8 | 9 | 10 | 17 | 17 | 20 | 24 | 30 |
(1)带备忘的自顶向下法:按照递归形式编写过程,但过程中会保存每一个子问题的解。当需要一个子问题的解时,过程首先检查是否已经保存过此解,若是则返回保存的值。
(2)自底向上法:当求解其子问题时,它所依赖的那些更小的子问题都已经求解完毕并且结果已经保存。
下面就贴程序源码了:
rodCutting.h:
#include<stdio.h> #include<stdlib.h> #include<limits.h> int memoizedCutRod(int *p,int n,int *r);//带备忘的自顶向下法 int extendedBottomUpCutRod(int *p,int n,int *r,int *s);//扩展的自底向上法 void printCutRodSolution(int *p,int n);//打印结果
rodCutting.cpp
#include"rodCutting.h" int memoizedCutRodAux(int *p,int n,int *r); int memoizedCutRod(int *p,int n,int *r){ int i; for(i=0;i<n+1;i++) r[i]=INT_MIN; return memoizedCutRodAux(p,n,r); } int memoizedCutRodAux(int *p,int n,int *r){ int q,i; if(r >=0) return r ; if(n==0) q=0; else{ q=INT_MIN; if(n<11){ for(i=1;i<n+1;i++){ int t=p[i]+memoizedCutRodAux(p,n-i,r); if(q<t){ q=t; } } } else{ for(i=1;i<11;i++){ int t=p[i]+memoizedCutRodAux(p,n-i,r); if(q<t){ q=t; } } } } r =q; return q; } int extendedBottomUpCutRod(int *p,int n,int *r,int *s){ r[0]=0; int i,j,q; for(j=1;j<n+1;j++){ q=INT_MIN; if(j<11){ for(i=1;i<=j;i++){ if(q<p[i]+r[j-i]){ q=p[i]+r[j-i]; s[j]=i; } } } else{ for(i=1;i<11;i++){ if(q<p[i]+r[j-i]){ q=p[i]+r[j-i]; s[j]=i; } } } r[j]=q; } return r ; } void printCutRodSolution(int *p,int n){ int *r,*s; r=(int *)malloc(sizeof(int)*(n+1)); s=(int *)malloc(sizeof(int)*(n+1)); int q; q=extendedBottomUpCutRod(p,n,r,s); printf("The max income is:%d\n",q); printf("The solution of the max income is:\n"); while(n>0){ printf("%d ",s ); n=n-s ; } }
main.cpp:
#include"rodCutting.h" int main(){ int p[11]={0,1,5,8,9,10,17,17,20,24,30}; int n,i; printf("Please input the length of the rod:\n"); scanf("%d",&n); int *r; r=(int *)malloc(sizeof(int)*(n+1)); int q; q=memoizedCutRod(p,n,r); printf("The maximum income is:%d\n",q); printf("Every little income is:\n"); for(i=0;i<n+1;i++){ printf("%d-%d ",i,r[i]); } printf("\n"); printCutRodSolution(p,n); system("pause"); return 0; }
相关文章推荐
- 小白进阶之动态规划-钢条切割
- 最大公约数最小公倍数
- centos安装python2.7和pip2.7
- 数据库编辑操作
- 日常小结-tomcat结构目录、web应用及虚拟目录的映射
- App通过QQ/微信登录绑定用户信息的一般流程
- 自定义带圆点ViewPager
- Android三种播放视频的方式
- C++中复制构造函数与重载赋值操作符总结
- Python中的字符串替换操作示例
- 设计模式-代理模式
- 排序算法-归并排序
- 数据库添加数据I
- 淘宝滑动验证码研究-后续
- Python实战1_2:爬取商品信息
- 快慢指针学习
- mysql auto_increment 初始值从0开始
- Android中Material Desgin风格的Snackbar、TextInputLayout、FloatingActionButton使用
- mysql 主从复制
- Java SE基础知识点总结(一)