01背包问题
题目要求:
有N件物品和一个容量为V的背包。第i件物品的费用是c,价值是w。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
算法分析:
n 若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题:
n 如果不放第i件物品,则转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];
n 如果放第i件物品,则转化为“前i-物品放入剩下的容量为v-c[i]的背包中”,最大价值就是f[i-1][v-c[i]]+w[i]。
n 所以子问题解决方式 f[j]=max{f[j],f[v-c[i]]+w[i]};
实现细节:
空间优化:
fori=1..N
for v=V..0
f[v]=max{f[v],f[v-c[i]]+w[i]};
初始化细节:
若要求恰好装满背包,初始化时除了f[0]为0其它f[1..V]均设为-∞
若没有要求必须把背包装满,初始化时将f[0..V]全部设为0
代码实现:
#include<bits/stdc++.h>
using namespace std;
struct goods
{
int c,w; //c为价钱,w为价值
}goods[10000];
int main()
{
int n,v,i,j;
int f[1000];
cin>>n>>v;
for(i=0;i<=v;i++) //背包不要求装满
f[i]=0;
for(i=0;i<n;i++)
cin>>goods[i].c>>goods[i].w;
for(i=0;i<n;i++)
{
for(j=v;j>goods[i].c;j--)
if(f[j]<f[j-goods[i].c]+goods[i].w) //子问题重要条件
f[j]=f[j-goods[i].c]+goods[i].w;
}
cout<<f[v]<<endl;
return 0;
}