题目:有N件物品和一个容量为V的背包,放入第i件物品耗费的空间是ci,得到的价值是wi,求解将哪些物品装入背包可使价值总和最大。
特点:每种物品只有一件,可以选择放或不放。
状态转移方程:f[i,v]=max(f[i-1,v],f[i-1,v-ci]+wi)
如果不放第i件物品,那么问题就转化为前i-1件物品放入剩下容量为v-ci的背包中,价值为f[i-1,v-ci]+wi。
o(vn) :for(i=1;i<=n;i++)
for(v=c[i];v<=V;v++)
f[i][v]=max(f[i-1][v],f[i-1][v-ci]+wi);
优化空间复杂度:
o(v): for(i=1;i<=n;i++)
for(v=V;v>=ci;v--)
f[v]=max(f[v],f[v-ci]+wi);
初始化细节:
恰好装满:f[0]=0; f[1...v]=-1;
不必装满:f[0...v]=0;
t=1
n=5 V=10
1、2、3、4、5(wi)
5、4、3、2、1(vi)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<map>
#include<queue>
using namespace std;
#define maxn 1010
int f[maxn],w[maxn],c[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,v;
memset(f,0,sizeof(f));
scanf("%d%d",&n,&v);
for(int i=0;i<n;i++)
scanf("%d",&w[i]);
for(int i=0;i<n;i++)
scanf("%d",&c[i]);
for(int i=0;i<n;i++)
{
for(int j=v;j>=c[i];j--)
{
f[j]=max(f[j],f[j-c[i]]+w[i]);
}
}
printf("%d\n",f[v]);
}
return 0;
}