背包DP的标准代码模板
来源:互联网 发布:python简介 编辑:程序博客网 时间:2024/05/23 02:01
提前声明,关于背包的思路在背包九讲里面已经很清楚了,这里只是把伪代码写成程序而已。
01背包
首先从最简单的01背包开始。
有N件物品和一个容量为V 的背包。放入第i件物品耗费的空间是Ci,得到的价值是Wi。求解将哪些物品装入背包可使价值总和最大。
标准代码以及注释如下
#include<iostream>using namespace std;#define MAXN 10000+5int f[MAXN],V;int max(int a,int b){ return a>b?a:b;}int main(){ int n; cin >> n >> V;//n是物品的个数,V是背包的体积。 for(int i=1,w,v;i<=n;i++) { cin >> w >> v;//w是物品的价值,v是物品的体积。 for(int i=V;i>=v;i--) f[i]=max(f[i],f[i-v]+w); } cout << f[V]; return 0;}
我们可以把01背包写成函数的形式,这样在调试的时候会方便很多。
那么函数版本如下
void ZeroOnePack(int w,int v){ for(int i=V;i>=v;i--) f[i]=max(f[i],f[i-v]+w);}
完全背包
01背包之后,让我们来看看完全背包。
有N种物品和一个容量为V的背包,每种物品都有无限件可用。放入第i种物品的耗费的空间是Ci,得到的价值是Wi。求解:将哪些物品装入背包,可使这些物品的耗费的空间总和不超过背包容量,且价值总和最大。
标准代码及注释如下
#include<iostream>using namespace std;#define MAXN 10000+5int max(int a,int b){ return a>b?a:b;}int main(){ int f[MAXN],n,V; cin >> n >> V; for(int i=1,w,v;i<=n;i++) { cin >> w >> v; for(int i=v;i<=V;i++)//其实就是把01背包反过来循环而已。 f[i]=max(f[i],f[i-v]+w); } cout << f[V]; return 0;}
同上,函数版本如下
void CompletePack(int w,int v){ for(int i=v;i<=V;i++) f[i]=max(f[i],f[i-v]+w);}
多重背包
那么,我们给每个物品加上数量的限制。
有N种物品和一个容量为V的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci,价值是Wi。求解将哪些物品装入背包可使这些物品的耗费的空间总和不超过背包容量,且价值总和最大。
标准代码以及注释如下
#include<iostream>using namespace std;#define MAXN 10000+5int main(){ int f[MAXN],n,V; cin >> n >> V; for(int i=1,w,v,num;i<=n;i++) { cin >> w >> v >> num;//这里多的num是每种物品的数量 if(num*v>=V)//如果说只拿这一种物品就能把背包放满,我们就把它视为完全背包。 for(int j=v;j<=V;j++) f[j]=max(f[j],f[j-v]+w); else//这里是将多重背包转换成01背包来做,可以单步执行几次,或者头脑加纸笔模拟一下,以加深理解。 { int k=1; while(k<num) { for(int j=V;j>=k*v;j--) f[j]=max(f[j],f[j-k*v]+k*w); num-=k; k*=2; } for(int j=V;j>=num*v;j--) f[j]=max(f[j],f[j-num*v]+num*w); } } cout << f[V]; return 0;}
函数版本如下
void MultiPack(int w,int v,int num){ if(num*v>=V) for(int j=v;j<=V;j++) f[j]=max(f[j],f[j-v]+w); else { int k=1; while(k<num) { for(int j=V;j>=k*v;j--) f[j]=max(f[j],f[j-k*v]+k*w); num-=k; k*=2; } for(int j=V;j>=num*v;j--) f[j]=max(f[j],f[j-num*v]+num*w); }}
我们还可以用01背包和完全背包的函数简化一下这个代码
void MultiPack(int w,int v,int num){ if(num*v>=V) CompletePack(w,v); else { int k=1; while(k<num) { ZeroOnePack(k*w,k*v); num-=k; k*=2; } ZeroOnePack(num*w,num*v); }}
混合背包
混合背包就是说一道题里面会有01背包,会有完全背包,会有多重背包。对于这种题目,我们只需要把前面三种背包的函数做一个整合,然后判断是哪一种物品,调用相应的函数即可。
泛化物品
考虑这样一种物品,它并没有固定的费用和价值,而是它的价值随着你分配给它的费用而变化。这就是泛化物品的概念。
泛化物品并没有什么固定的代码,它是随着题目给出的关系式变化而变化的。我们要根据不同题目的要求来进行改动,但大致是这样的思路:
void GeneralizationPack(...){ for(int i=V;i>=1;i--) for(int x=1;x<=i;x++) f[i]=max(f[i],f[i-x]+...);}
【P.S.】…在这里代表的是不固定的内容,会根据题意变化的
那么假设我们分配的体积x与价值y的关系是这样y=a*x^2-b*x,则
void GeneralizationPack(int A,int B){ for(int i=V;i>=1;i--) for(int x=1;x<=i;x++) f[i]=max(f[i],f[i-x]+A*x*x-B*x);}
- 背包DP的标准代码模板
- 背包问题标准模板
- 背包的标准代码与注释
- 背包dp模板
- Dp&&背包_模板
- dp 01背包,完全背包,多重背包 模板
- 二维背包问题 + 代码模板
- dp之01背包代码
- dp-01背包问题代码
- 树形DP—依赖背包模板
- 01背包,完全背包,多重背包 ,模板代码
- 01背包、完全背包、多重背包模板代码
- 自己的背包模板
- [DP][01背包]01\完全\多重背包模板
- CODE[VS]3269 混合背包 (背包DP模板集合)
- 堆的标准模板
- 树型DP,树上的背包
- 背包问题的代码
- C++Primer第五版 10.1节练习
- Oracle建立表空间、建立用户、用户授权、指定表空间、激活用户、删除用户、删除表空间
- HDU 5441 Travel(并查集)
- 平方和
- 2015.9.17 第十一堂 内存管理(下) [注:时间为学习时间,非原时间]
- 背包DP的标准代码模板
- UI_模态跳转
- 更改Oracle数据库的编码格式,解决导入时ORA-12899错误
- 面向对象复数类(class Complex) 的重载运算符 一元二元的实现与使用
- Oracle 序列 触发器的使用
- Android多媒体之调用摄像头和从本地相册中选择图片
- 数据结构与算法的笔记(一)
- KVO初级
- 文本输入控件 UITextField