算法学习笔记----用动态规划解决钢管切割问题
(说明:由于CSDN的博客中不能添加下标等特殊符号,所以部分内容使用截图的形式)
通过对问题进行高度抽象,现在我们的问题,就是要递归地求解r
n 的最大值,下面采用的是一种自顶向下的递归方法:
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的钢条不仅计算最大收益值r j,还保存最优解对应的第一段钢条的切割长度s j(也就是我们前边说到的左边一段的长度,这段是不再进行切割的):
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];
}
}
推荐阅读
- EffectiveObjective-C2.0|EffectiveObjective-C2.0 笔记 - 第二部分
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- Android中的AES加密-下
- 画解算法(1.|画解算法:1. 两数之和)
- Guava|Guava RateLimiter与限流算法
- 一起来学习C语言的字符串转换函数
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)