今天看了一下《算法导论》的第204页的钢条切割问题,如题:
一段钢条的长度i与价格p的关系为: i=1 p=1 i=2 p=5 i=3 p=8 i=4 p=9 i=5 p=10 i=6 p=17 i=7 p=17 i=8 p=20 i=9 p=24 i=10 p=30 问:给定一个长度为n的钢条,如何切割,使收益r最大?
思路:首先,钢条切割问题满足最优子结构性质:即问题的最优解是由相关子问题的最优解组合而成,而这些子问题可以独立求解。用动态规划的方法,从最小规模的子问题入手,每个子问题只需求解一次,将它保存到数组s里。这样从小到大的顺序求解,那么求解某个子问题时,它所依赖的更小的子问题已经求解完毕,结果已经保存。我根据书上的伪代码写出了c语言版的,代码如下:
#include "stdafx.h"
#include <stdio.h>
#include <limits.h>
#define N 100//定义数组的长度,只要比钢条长就ok
int r[N]={0},s[N]={0},q;//用数组r来记录最优收益 用数组s来记录切割方案
int p[]={0,1,5,8,9,10,17,17,20,24,30};//价格表
externded_bottom_up_cut_rod(int n){
r[0]=0;//长度为0时收益为0
for(int j=1;j<=n;j++){
q=INT_MIN;//利用<limits.h>里的无穷小
for(int i=1;i<=j;i++){
if(q<p[i]+r[j-i]){
q=p[i]+r[j-i];
s[j]=i;//保存最优解中第一段钢条的长度
}
}
r[j]=q;//将规模为j的子问题的解存入r【j】
}
return 0;
}
void main(){
int n=7;
externded_bottom_up_cut_rod(n);
printf("最优收益为%d\n",r[n]);
printf("最优切割方案是:");
while (n>0){
printf("%d\n",s[n]);
n=n-s[n];
}
}
这就是自底向上的方法。