背包问题总览(图)
2016-06-10 21:32
387 查看
猛然心血来潮写了一黑板的背包问题总览。
小班同志可以根据这顺序学习DP解决背包问题。
这个脑图很清楚的写出了背包问题的基本类别和思路(思路好像上厕所去了……)
总结和模板改天有空发上来。
ps:微软这个扫描软件真管用……前几天扫身份证,今天扫黑板,很方便。
[b]简单的背包问题(洛谷试炼场->普及练习场->动态规划的背包问题):[/b]
(一)01背包 (大部分可直接用模板解决):
(1)洛谷【p1060】开心的金明 (标准的01背包问题)
(2)洛谷【p1048】采药 (标准的01背包问题)
(3)洛谷【p1049】装箱问题 (01背包问题,物品重量和价值相同)
(二)背包方案计数:
(2)洛谷【P1164】 小A点菜 (01背包解决方案计数问题)
(三)依赖背包问题:
(1)洛谷 【p1064】金明的预算方案 (树状DP)
(四)完全背包问题:
(1)洛谷 【p1616】疯狂的采药 (每种物品有无限数量的背包问题)
小班同志可以根据这顺序学习DP解决背包问题。
这个脑图很清楚的写出了背包问题的基本类别和思路(思路好像上厕所去了……)
总结和模板改天有空发上来。
ps:微软这个扫描软件真管用……前几天扫身份证,今天扫黑板,很方便。
[b]简单的背包问题(洛谷试炼场->普及练习场->动态规划的背包问题):[/b]
(一)01背包 (大部分可直接用模板解决):
(1)洛谷【p1060】开心的金明 (标准的01背包问题)
#include<iostream> #include<cstdio> using namespace std; int N,m; int v[300],p[300]; int f[50001]; int want=0; int main(){ cin>>N>>m; for(int i=0;i<m;i++){ cin>>v[i]>>p[i]; p[i] *= v[i]; } for(int i=0;i<m;i++){ for(int j=N;j>v[i];j--){ if(f[j-v[i]]+p[i]>f[j]){ f[j]=f[j-v[i]]+p[i]; } } } cout<<f ; return 0; }
(2)洛谷【p1048】采药 (标准的01背包问题)
#include<cstdio> #include<iostream> using namespace std; int T,m; int w[1000],c[1000],f[100000]; int main() { cin>>T>>m; for(int i=1;i<=m;i++){ cin>>w[i]>>c[i]; } for(int i=1;i<=m;i++){ for(int j = T;j>=w[i];j--){ if(f[j-w[i]]+c[i]>f[j]){ f[j]= f[j-w[i]]+c[i]; } } } cout<<f[T]; }
(3)洛谷【p1049】装箱问题 (01背包问题,物品重量和价值相同)
#include<iostream> #include<cstdio> using namespace std; int v,n; int c[35],f[100000]; int main() { cin>>v>>n; for(int i =1;i<=n;i++){ cin>>c[i]; } for(int i =1;i<=n;i++){ for(int j=v;j>=c[i];j--){ if(f[j-c[i]]+c[i]>f[j]){ f[j]=f[j-c[i]]+c[i]; } } } cout<<v-f[v]; }
(二)背包方案计数:
(2)洛谷【P1164】 小A点菜 (01背包解决方案计数问题)
#include<iostream> #include<cstdio> using namespace std; int c[2000]; long long int f[100000]; int n,m; int main(){ cin>>n>>m; for(int i=0;i<n;i++){ cin>>c[i]; } f[0]=1; for(int i =0;i<n;i++){ for(int j=m;j>=c[i];j--){ f[j]+=f[j-c[i]]; } } cout<<f[m]; }
(三)依赖背包问题:
(1)洛谷 【p1064】金明的预算方案 (树状DP)
/*代码参考神犇博客*/ #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; const int M = 3276; const int S = 80; vector<int> vct[S]; vector<pair<int, int> > groups[S]; int dp[M], n, m, w[S], v[S], d[S]; main() { scanf("%d %d", &m, &n); m /= 10; for(int i = 1; i <= n; i++) { scanf("%d %d %d", &w[i], &v[i], &d[i]); w[i] /= 10; v[i] *= w[i]; if(d[i]) vct[d[i]].push_back(i); } int cnt = 0; for(int i = 1; i <= n; i++) { if(d[i] == 0) { memset(dp, 0, sizeof(dp)); dp[w[i]] = v[i]; int sum = w[i]; for(int j = 0; j < vct[i].size(); j++) { int dx = vct[i][j]; sum += w[dx]; for(int k = sum; k >= w[i]; k--) if(dp[k] != 0) dp[k + w[dx]] = max(dp[k] + v[dx], dp[k + w[dx]]); } for(int j = w[i]; j <= sum; j++) if(dp[j]) groups[cnt].push_back(make_pair(j, dp[j])); cnt++; } } memset(dp, 0, sizeof(dp)); for(int i = 0; i < cnt; i++) for(int j = m; j >= 0; j--) for(vector<pair<int, int> >::iterator it = groups[i].begin(); it != groups[i].end(); it++) if(j >= it ->first) dp[j] = max(dp[j], dp[j - it ->first] + it ->second); printf("%d\n", dp[m] * 10); }
(四)完全背包问题:
(1)洛谷 【p1616】疯狂的采药 (每种物品有无限数量的背包问题)
#include<iostream> #include<cstdio> using namespace std; int m,n; int f[100010],w[10010],c[10010]; int main(){ cin>>m>>n; for(int i=1;i<=n;i++){ cin>>w[i]>>c[i]; } for(int i=1;i<=n;i++){ for(int j = w[i];j<=m;j++){ if(f[j-w[i]]+c[i]>f[j]) f[j] = f[j-w[i]]+c[i]; } } cout<<f[m]; }
相关文章推荐
- Activity之间传递数据方式
- 如何为MyEclipse添加XML文档所使用的DTD
- 闭包 closure
- C. Tic-tac-toe【模拟】
- 测试驱动开发?
- SCPPO(二):禅道的使用—管理员
- Latex 初学者入门(四)-- 多个作者共享同一个地址
- 《互联网+医疗:重构医疗生态》,第四章介绍美国的医药福利管理制度与企业,值得看看,其他章节一般。总体二星。
- CSAPP3e - x86-64 assembly code analysis - Attack Lab: Level I
- Android Studio之could not reserve enough space for object heap报错
- GUIDE D'IONIC [Français]
- BLE4.0 BLE4.1 和BLE4.2 的主要区别
- HAILSTONE
- 【C语言】15-预处理指令1-宏定义
- 第121课: Spark Streaming性能优化:通过摄像头图像处理案例来说明Spark流处理性能评估新方法及性能调优参数测试
- LaTeX输入极限下标,输入目标函数中的max下标约束条件
- 无权最短路径
- 160. Intersection of Two Linked Lists
- Qt 技巧: 解决未解析的SSL问题
- android activity知识总结