算法学习笔记----用动态规划解决钢管切割问题

来源:互联网 发布:信托网络投票公司 编辑:程序博客网 时间:2024/04/30 06:06
(说明:由于CSDN的博客中不能添加下标等特殊符号,所以部分内容使用截图的形式)


通过对问题进行高度抽象,现在我们的问题,就是要递归地求解rn 的最大值,下面采用的是一种自顶向下的递归方法:
int p[] = {1, 5, 8, 9, 10, 17, 17,           20, 24, 30};static inline int max(i, j){    return (i > j ? i : j);}int cut_mod(int *p, int n){    int i;    int q;    if (n == 0) {        return 0;    }    q = -1;    for (i = 0; i < n; ++i) {        q = max(q, p[i] + cut_mod(p, n - i - 1));    }    return q;}

int bottom_up_cut_mod(int *p, int n){    int i, j, q;    int r[n + 1];    r[0] = 0;    for (j = 1; j <= n; ++j) {        q = -1;        for (i = 1; i <= j; ++i) {            q = max(q, p[i - 1] + r[j - i]);        }        r[j] = q;    }    return r[n];}
  实现中max()函数及p的定义参见cut_mod()的实现。这里对实现做一个说明:第一个循环计算的是来选择长度,长度为j;第二个循环是计算长度为j时的最优解。过程是这样的:当j为1时,也就是说此时长度为1,这时最优解q=max(-1,p[0]+r[0]),此时q=p[0],即长度为1英寸的钢条的售价;当j为2时,此时长度为2,这时最优解就要在i=1和i=2之间进行选择,而i=1时的值在第一次循环中已计算出来保存在r数组中,i=2时等于是不切割。所以每次循环计算到j时,依赖的j-1对应的最优解已经计算出来,不需要再重复计算。
  bottom_up_cut_mod()的实现只是给出了最优解,但是并没有保存最优解方案,也就是如何来切割。下面给出的bottom_up_cut_rod()的扩展版本,它对长度为j的钢条不仅计算最大收益值rj,还保存最优解对应的第一段钢条的切割长度sj(也就是我们前边说到的左边一段的长度,这段是不再进行切割的):
int extend_bottom_up_cut_mod(int *p, int n, int *s){    int i, j, q;    int r[n + 1];    r[0] = 0;    for (j = 1; j <= n; ++j) {        q = -1;        for (i = 1; i <= j; ++i) {            if (q < p[i - 1] + r[j - i]) {                q = p[i - 1] + r[j - i];                s[j] = i;            }        }        r[j] = q;    }    return r[n];}static void print_cut_mod_solution(int n, int *s){    while (n) {        printf("%d ", s[n]);        n = n - s[n];    }}
原创粉丝点击