01背包问题 -- 经典动态规划题
2016-03-16 14:51
686 查看
01背包问题
问题描述:有n个重量和价值分别为Wi,Vi的物品,从这些物品中挑选出总重量不超过W的物品,求怎么挑选才能使价值最大;
首先可以使用搜索来看看,吧每件物品放入背包试试,找出最优解。
每一次搜索都是要两次分支,所以如果物品一多就会运行效率特别慢。
运行截图:
![](http://img.blog.csdn.net/20160316145852197)
可以看到如果只用搜索的话会有重复的调用。所以我可以吧第一次的计算记录下来
所以我们只要把第一次计算的结果保留到一个数组中记录下来,如果再次遇到重复的计算直接使用这个计算结果即可
这样略微改进就可以优化整个程序,是可接问题的规模大幅度提高
然后要上一个真正的动态规划啦,其实根据上面的记忆化搜索就可以推出状态转移方程了:
根据整个状态转移方程就可以写出程序了
代码如下:
问题描述:有n个重量和价值分别为Wi,Vi的物品,从这些物品中挑选出总重量不超过W的物品,求怎么挑选才能使价值最大;
首先可以使用搜索来看看,吧每件物品放入背包试试,找出最优解。
// 01背包问题 // 问题描述: // 有一个背包可以存放W重量的物品,有n样物品,价值分别为v1,v2,v3,……vn, // 重量分别为w1,w2,w3,……wn,求怎么放才能让价值最大 // 首先不使用动态搜索,只使用深度搜索来解决问题。 // 搜索的方法是 #include <iostream> #include <algorithm> using namespace std; const int MAX_N = 1005; int W; // 背包最大重量 int N; // 物品数量 struct Res // 定义物品 { int weight; int value; }res[MAX_N]; int dfs(int i, int j); // i代表搜索第几个物品, j代表还可以放入多少重量的物品 int main() { cout <<"请输入背包的最大存放重量"; cin >> W; cout << "请输入物品的数量:"; cin >> N; cout << "请输入每件物品的重量和价值:\n"; for(int i = 0; i < N; i++) cin >> res[i].weight >> res[i].value; int ans = dfs(0, W); cout << ans << endl; return 0; } int dfs(int i, int j) { int ans; if(i == N) // 如果搜索到最后一个 ans = 0; else if(j < res[i].weight) // 如果当前的物品不能放入背包 ans = dfs(i + 1, j); else // 比较挑选和不挑选的情况都尝试一下返回最优解 ans = max(dfs(i + 1, j), dfs(i + 1, j - res[i].weight) + res[i].value); return ans; }
每一次搜索都是要两次分支,所以如果物品一多就会运行效率特别慢。
运行截图:
可以看到如果只用搜索的话会有重复的调用。所以我可以吧第一次的计算记录下来
所以我们只要把第一次计算的结果保留到一个数组中记录下来,如果再次遇到重复的计算直接使用这个计算结果即可
// 使用二维数组记录结果,避免了搜索中的重复调用,优化搜索过程,称为记忆化搜索 #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int MAX_N = 1005; struct RES { int weight; int value; }res[MAX_N]; int W, N; int DP[MAX_N][MAX_N]; int dfs(int i, int j); int main() { cout <<"请输入背包的最大存放重量"; cin >> W; cout << "请输入物品的数量:"; cin >> N; cout << "请输入每件物品的重量和价值:\n"; for(int i = 0; i < N; i++) cin >> res[i].weight >> res[i].value; memset(DP, -1, sizeof(DP)); int ans = dfs(0, W); cout << ans << endl; return 0; } int dfs(int i, int j) { if(DP[i][j] >= 0) return DP[i][j]; int reslut; if(i == j) reslut = 0; else if(j < res[i].weight) reslut = dfs(i + 1, j); else reslut = max(dfs(i + 1, j), dfs(i + 1, j - res[i].weight) + res[i].value); return DP[i][j] = reslut; }
这样略微改进就可以优化整个程序,是可接问题的规模大幅度提高
然后要上一个真正的动态规划啦,其实根据上面的记忆化搜索就可以推出状态转移方程了:
DP = DP[i + 1][j]; (j < res[i].weight) DP = max(DP[i + 1][ j], DP[i + 1][ j - res[i].weight] + res[i].value)
根据整个状态转移方程就可以写出程序了
代码如下:
#include <iostream> #include <algorithm> #include <cstring> using namespace std; const int MAX_N = 1005; struct RES { int weight; int value; }res[MAX_N]; int W, N; int DP[MAX_N][MAX_N]; int main() { cout <<"请输入背包的最大存放重量"; cin >> W; cout << "请输入物品的数量:"; cin >> N; cout << "请输入每件物品的重量和价值:\n"; for(int i = 0; i < N; i++) cin >> res[i].weight >> res[i].value; memset(DP, 0, sizeof(DP)); for(int i = N - 1; i >= 0; i--) for(int j = 0; j <= W; j++) if(j < res[i].weight) DP[i][j] = DP[i + 1][j]; else DP[i][j] = max(DP[i + 1][j], DP[i + 1][j -res[i].weight] + res[i].value); cout << DP[0][W]; return 0; }
相关文章推荐
- Pointwise 17.3 R4 安装及破解【详细图文】
- createrepo:创建本地源
- JS判断密码强度的代码
- iOS 中的UIWebview如何添加头视图的问题
- QT编码问题之不规则对话框的实现
- 纯数字逐一停止显示效果
- 数据结构与算法学习笔记(五)
- SSRS 报表 递归列表
- 2、工厂方法模式
- 如何引入一个Schema 文件
- jquery tab
- sublime中配置Java 环境
- ngrep undefined symbol: pcap_restart 错误处理
- 310. Minimum Height Trees LeetCode
- 网络管理-NTP的配置
- la 4945 free goodies,不会!
- 高性能网站架构的思考
- PAT (Advanced Level) Practise 1054 The Dominant Color (20)
- 详解印染产品纬斜疵病产生原因及如何预防
- SQL统计查询(按月份)