背包问题大体上有三种类型,分别是0-1背包,完全背包和介于其中的背包问题。其中又有很多小的细节改变,比如说背包是否要求刚好装满。一般求解的是背包不要求刚好装满,只要求在限制范围内的最大价值就可以。
0-1背包的思路是这样的,不断地向背包添加物品,对于一个物品,当背包容量为v时,选择是添加当前物品进背包还是不添加直
接用前面的安排。V[j][C] = max{V[j-1][C],V[j-1][C-w[j]]+value[j] },表示选择不添加当前这个背包还是添加这个背包,对应的例子:
No | weight | value |
1 | 2 | 3 |
2 | 3 | 4 |
3 | 4 | 5 |
1 | 2 | 3 | 4 | 5 | |
1 | 0 | 3 | 3 | 3 | 3 |
2 | 0 | 3 | 4 | 4 | 7 |
3 | 0 | 3 | 4 | 4 | 7 |
对于完全背包C=1开始,这样C-W[I]就是可以被添加多次的此次被计算过的最大值。
完全背包上面的例子的状态应该是:
1 | 2 | 3 | 4 | 5 | |
1 | 0 | 3 | 3 | 6 | 6 |
2 | 0 | 3 | 4 | 6 | 7 |
3 | 0 | 3 | 4 | 6 | 7 |
for(int i=0;i<n;i++)
for(int j= V;j>=0;j--)
{
if(j>=weight[i])
{
if(f[j-weight[i]]+value[i]>f[j])
f[j] = f[j-weight[i]]+value[i];
}
}
完全背包的时候最优空间的解法方程是:
for(int i=0;i<n;i++)
for(int j= 0;j<=V;j++)
{
if(j>=weight[i])
{
if(f[j-weight[i]]+value[i]>f[j])
f[j] = f[j-weight[i]]+value[i];
}
}
0-1背包 code :
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
int n,V;
cin>>n>>V;
int value[n],weight[n];
for(int i=0;i<n;i++)
cin>>value[i]>>weight[i];
int f[V+1]; //此时不要求刚好装满背包,所以可以将f[V]初始化为0,f[V]存放的是当V为背包容量时,最大地放入价值
memset(f,0,(V+1)*sizeof(int));
for(int i=0;i<n;i++)
for(int j= V;j>=0;j--)
{
if(j>=weight[i])
{
if(f[j-weight[i]]+value[i]>f[j])
f[j] = f[j-weight[i]]+value[i];
}
cout<<"i="<<i<<" j="<<j<<":"<<f[j]<<endl;
}
cout<<f[V]<<endl;
return 0;
}
完全背包code:
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
int n,V;
cin>>n>>V;
int value[n],weight[n];
for(int i=0;i<n;i++)
cin>>value[i]>>weight[i];
int f[V+1]; //此时不要求刚好装满背包,所以可以将f[V]初始化为0,f[V]存放的是当V为背包容量时,最大地放入价值
memset(f,0,(V+1)*sizeof(int));
for(int i=0;i<n;i++)
for(int j= 0;j<=V;j++)
{
if(j>=weight[i])
{
if(f[j-weight[i]]+value[i]>f[j])
f[j] = f[j-weight[i]]+value[i];
}
cout<<"i="<<i<<" j="<<j<<":"<<f[j]<<endl;
}
cout<<f[V]<<endl;
return 0;
}
学习链接:http://wenku.baidu.com/view/82d6c300de80d4d8d15a4f8d.html#
http://wenku.baidu.com/link?url=19k7mBFMIMvDhkqqwwnZvoPLMLtVB88SG7Fd1tINVxSc1BeY46sVj02D64IO8a-mqfcN4_tI9Q4OP_7xIVQz64q5tvntiMuk6yWSiUzIp8q