您的位置:首页 > 其它

小白进阶之动态规划-钢条切割

2016-06-27 18:47 183 查看
关于动态规划算法,首先是:

什么样子的问题适合用动态规划算法来解呢?

适合用动态规划算法解的问题应具有两个性质:最优子结构性质和具有重复子问题

最优子结构性质是指:若一个问题的最优解包含其子问题的最优解,则此问题具有最优子结构性质。

具有重复子问题性质是指:问题的递归算法会反复求解相同的子问题。

然后是:

动态规划算法的设计有四个步骤:

1.刻画一个最优解的结构特征-寻找最优子结构;

2.递归地定义最优解的值;

3.计算最优解的值,通常采用自底向上的方法;

4.利用计算出的信息构造一个最优解。

动态规划算法有4个经典问题:钢条切割、矩阵链乘法、最长公共子序列、最优二叉搜索树。

本文会解决钢条切割问题,其他问题会后面的文章中解决。

钢条切割

给定一段长度为n英寸的钢条和一个价格表,求切割钢条的方案,使受益最大。

求解方法:将钢条从左边切下长度为i的一段,只对右边剩下的长度为n-i的一段继续切。

价格表如下:

长度i12345678910
价格p[i]1589101717202430
动态规划求解有两种方法:带备忘的自顶向下法和自底向上法,期望运行时间都为:θ(n²)。
(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: