记得以前学数据结构的时候,经常能看到关于背包问题的题目,好像acm比较多一点,心底觉得比较难。这两天看了一下,感觉想复杂了、、、
0-1 背包问题是给定 n 种物品和一个容量为 C 的背包,物品 i 的重量是 wi,其价值为 vi,每样物品只可取一次,并希望不超容量的前提下,能拿到价值最多的物品
我们假设一个情景,有5件物品,(重量,价值)分别为A(2,3),B(4,5),C(3,3),D(6,8),E(4,6),包容量为10
我们需要绘制出一个表
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
A | 0 | 0 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
B | 0 | 0 | 3 | 3 | 5 | 5 | 8 | 8 | 8 | 8 | 8 |
C | 0 | 0 | 3 | 3 | 5 | 6 | 8 | 8 | 8 | 11 | 11 |
D | 0 | 0 | 3 | 3 | 5 | 6 | 8 | 8 | 11 | 11 | 13 |
E | 0 | 0 | 3 | 3 | 6 | 6 | 9 | 9 | 11 | 12 | 14 |
A0表示只有A物品的情况下,背包容量为0,则能容纳最大价值为0
B2表示只有A和B物品的情况下,背包容量为2,则能容纳的最大价值为3
01背包问题,因为每件物品只有一件,考虑的是是否将其放入背包。而表中的每一个数据,也是由两个数据决定的,就拿C5这个数据来说,他参考的是B5和B2的值:参考B5是不放入C的情况;参考B2是想去放入C,因为背包容量为5,那么就要考虑仅有A、B存在时,背包容量为3时的最大价值
所以重点是如何去构建二维数组。第一行和第一列比较特殊,可以直接填写;数组中其它元素可以通过比较来获得,不过需要比较一下背包容量和将要放入物品的重量,比如说C5,5要大于C重量3的,因而可以比较B5与B2的大小,要是填写C2的话,就只能参考B2了
C++代码
#include<iostream>
#define N 5
#define C 10
using namespace std;
typedef struct ITEM{
int weight;
int value;
}item;
int main(){
ITEM item[N];
int ans[N][C+1];
for(int i=0;i<N;i++){
cin>>item[i].weight>>item[i].value;
}
for(int i=0;i<N;i++){
for(int j=0;j<C+1;j++){
if(i==0||j==0){
if(j<item[i].weight)
ans[i][j]=0;
else
ans[i][j]=item[i].value;
}
else{
if(j<item[i].weight)
ans[i][j]=ans[i-1][j];
else
ans[i][j]=ans[i-1][j]>ans[i-1][j-item[i].weight]+item[i].value?ans[i-1][j]:ans[i-1][j-item[i].weight]+item[i].value;
}
}
}
for(int i=0;i<N;i++){
for(int j=0;j<C+1;j++)
cout<<ans[i][j]<<" ";
cout<<endl;
}
return 0;
}
运行结果: