动态规划有很多实例,例如:01背包问题,
01背包
一共有四样物品,你有一个背包,背包固定容量,并且物品所占一定容量,具有一定价值。
例:
现有四件物品,背包总容量为8,要求背包装价值最多的物品。
物品编号 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
物品重量 | 2 | 3 | 4 | 5 |
物品价值 | 3 | 4 | 5 | 8 |
记:f(k,w):当背包容量为w,现有k件物品可以拿,所能拿到最大价值。
f(4,8)——可拿4号,背包容量8。
- 拿4号物品,f(3,3)+8,可拿3号,容量3,价值得到8。
- 不拿4号,f(3,8),可拿3号,容量为8,价值得到零。
现存两种情况 拿与不拿;即:f(3,3)+8和f(3,8);
- f(3.3)+8
3号物品重量为4,4>3,4号物品重量大于背包剩余容量,背包装不下了。所以:目前为f(2,3)+8。
余下:拿2号和不拿2号。
拿:f(1,0)+8+4=f(1,0)+12 再无容量 装包结束
不拿:f(1,3)+8 继续:拿1号f(0,1)+8+3=f(0,1)+11不拿:f(0,3)+8 - 以此类推 进行比较取价值最大的。f(1,0)+12
f(k,w)=f(k-1,w),wk>w (物品容量大于背包剩余容量,装不下)
f(k,w)=max(f(k-1,w),f(k-1,w-wk)+vk),wk<=w(主要就是找最大的)
代码实现
板子
来源于实验室学长的传授,做题时有所改动,但大体类似。
#include<stdio.h>
#include<algorithm>
using namespace std;
#include<iostream>
#include<cstring>
#include<queue>
#define MAX 10050
#define INF 0X3f3f3f
int v[MAX], w[MAX],n,W,t,opt[MAX][MAX];
int main() {
int t;
while(cin>>t) {
while(t--) {
ciin>>n>>w;
for(int i=1; i<=n; i++) {
cin>>w[i];
}
for(int i=0; i<=n; i++) {
cin>>w[i];
}
memset(opt,0,sizeof(opt));
for(int i=1; i<=n; i++) {
for(int j=0; j<=w; j++) {
if(j<w[i]) {
opt[i][j]=opt[i-1][j];
} else {
opt[i][j]=max(opt[i-1][j],opt[i-1][j-w[i]]+v[i]);
}
}
}
cout<<opt[n][w]<<endl;
}
}
return 0;
}
此为背包plus 学长传授 灵活运用即可
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0x3f3f3f
#define MAX 1010
struct ITEM { //为多重背包问题结构体,便于队列优化
int wd;
int vd;
ITEM (int ww, int vv) {
wd = ww;
vd = vv;
}
};
queue <ITEM> items;//队列 优化多重背包
int n,W; //物种数,背包限制载荷
int w[MAX];//每种物品重量
int v[MAX];//每种物品价值
int dp[MAX][MAX];//基础价值求和表
int f[MAX];//进阶表
int num;//队列中元素个数
void OIpack ( ) {//01背包基础
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= W; j++) {
if( j < w[i]) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = max( dp[i - 1][j],dp[i - 1][j - w[i]] + v[i]);
}
}
}
}
void OIPAXK ( ) { //01背包进阶
for(int i = 1; i <=n; i++) {
for(int j=W; j >= w[i]; j--) {
f[j] = max( f[j], f[j - w[i]] +v[i]);
}
}
}
void fullpack( ) { //完全背包
memset(f, 0, sizeof(f));//当要求价值最大且需装满时 memset (f, -INF, sizeof(f));
for(int i = 1; i <= n; i++) { //
for(int j = w[i]; j <= W; j++) { //
f[j] = max(f[j], f[j - w[i]] + v[i]); //f[j] = max(f[j], f[j - w[i]] + v[i];
}
}
}
void OIinit( ) {//01基础背包输入
memset ( dp ,0, sizeof( dp));
cin >> n >> W;
for(int i = 1; i <= n; i++) {
cin >> w[i] >> v[i];
}
return;
}
void Mulpack( ) { //多重背包
while( !items.empty( )) {
ITEM d=items.front( );
for(int j = W; j >= d.wd; j--) {
f[j] = max( f[j], f[j - d.wd] + d.vd);
}
items.pop( );
}
}
void Mulinit( ) { //多重背包输入
memset (f, 0, sizeof(f));
num = 0;
cin >> n >> W;
int a, b, s;
for(int i = 1; i <= n; i++) {
cin >> a >> b >> s;
ITEM x( a, b);
for(int j = 0; j < s; j++) {
items.push(x);
num++;
}
}
}
void OIout1( ) { //输出
cout << dp[n][W] << endl;
}
void OIout2( ) {
cout<< f[W] <<endl;
}
int main( ) {
// Mulinit( );
// Mulpack( );
// OIout2( );
OIinit( );
OIpack( );
OIout1( );
}