[算法学习笔记]动态规划之钢条切割问题
2016-08-05 14:10
393 查看
问题描述
有一个长度为n的钢条需要切割成短钢条出售,长度不同的钢条售价也不同,如下:长度i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
价格p[i] | 1 | 5 | 8 | 9 | 10 | 17 | 17 | 20 | 24 | 30 |
暴力解决思路
只要列出每种切割方案,然后比较一下哪种切割方案利润最大不就可以了吗(手动滑稽假设有一个长度为4的钢条,那么有一下四中切割方案
编号 | 切割方案 | 利润 |
---|---|---|
① | ■■■■ | 9 |
② | ■■■,■ | 9 |
③ | ■■,■■ | 10 |
④ | ■■,■,■ | 6 |
⑤ | ■,■,■,■ | 4 |
钢条切割问题满足最优子结构的性质:问题的最优解由相关问题的最优解组合而成,而这些子问题可以独立求解。
通过递归的求解方式可以写出简单的求解程序:从钢条的左边切割下一段长度为i的短钢条,然后右边为长度就为n-i的短钢条,然后对右边继续递归求解,知道右边的长度为0,则返回零。
#include <stdio.h> #define max(a,b) (a>b?a:b) #define INF 0x7fffff; // 不同长度钢条的价格 int p[11] = { 0,1,5,8,9,10,17,17,20,24,30 }; int cutROd(int p[], int n){ int i, q; if(n == 0) return 0; q = -INF; for(i = 1; i <= n; i++){ q = max(q, p[i] + cutROd(p, n - i)); } return q; } int main(){ int n; scanf("%d", &n); printf("%d\n", cutROd(p, n)); return 0; }
指数爆炸
图样图森破啊,这个程序的复杂度是2^n,所以输入大一点的数就会指数爆炸了,等半天结果才会出来,所以这样写太native了更高效的方法
改进上面的程序
上面的程序之所以低效,因为有很多重复的计算啊,比如说计算长度为4的钢条,便有多次计算了长度为2和3的最优解,更不要说在大一点的数要重复计算多少次了。但是,如果能避免这些重复计算的,算法的效率就会非常高了,只要在第一次计算中吧结果记录下来,下次需要用到的时候直接调用就可以了。#include <stdio.h> #define max(a,b) (a>b?a:b) #define INF 0x7fffff; int p[11] = { 0,1,5,8,9,10,17,17,20,24,30 }; int memoizedCutRodAux(int p[], int n, int r[]){ int q; if(r >= 0) return r ; if(n == 0) q = 0; else{ q = -INF; int i; for(i = 1; i <= n; i++) q = max(q, p[i] + memoizedCutRodAux(p, n-i, r)) ; } r = q; return q; } int memoizedCutRod(int p[], int n){ int r[11], i; for(i = 0; i < 11; i++) r[i] = -INF; return memoizedCutRodAux(p, n, r); } int main(){ int n; scanf("%d", &n); printf("%d\n", memoizedCutRod(p, n)); return 0; }
另一种解法
#include <stdio.h> #define max(a,b) (a>b?a:b) #define INF 0x7fffff; int p[11] = { 0,1,5,8,9,10,17,17,20,24,30 }; int buttomUpCutRod(int p[], int n){ int r[n+1]; r[0] = 0; int i, j; for(i = 1; i <= n; i++){ int q = -INF; for(j = 1; j <= i; j++) q = max(q, p[j] + r[i - j]); r[i] = q; } return r ; } int main(){ int n; scanf("%d", &n); printf("%d\n", buttomUpCutRod(p, n)); return 0; }
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法