题目:
有一个箱子容量为V(正整数,0≤V≤20000),同时有n个物品(0<n≤30),每个物品有一个体积(正整数)。要求从n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
Input
输入有多组测试数据,第一行一个正整数V,表示箱子的容量
第二行一个数据n表示物品个数。
第三行有n个数据,描述每个物品的体积
Output
每个输出占一行,输出箱子最后剩下的最小体积
Sample Input
24 一个整数,表示箱子容量
6 一个整数,表示有n个物品
8 3 12 7 9 7分别表示这n个物品的各自体积
Sample Output
0 一个整数,表示箱子剩余空间
hint:汉字是不需要处理的,只是为了描述题目
你也可以考虑其他的方法。
分析:
简单的01背包模型,一个容量为v的背包,n个物品的价值和重量相等,问题转化为容量为v的背包能装下的最大价值。用dp(i,j)表示考虑了第i个物品后,剩余容量为j的背包能装下的最大价值。对第i个物品有放或不放两种情况,故有转移方程dp(I,j)=max(dp(i-1,j),dp(i-1,j-w[i])+c[i] );还可优化空间负责度,因为对于每一维,dp[][j]总是从dp[][j-w[i]]和dp[][j]推导出来,所以可优化为一维的空间复杂度。有转移方程dp(v)=max(dp(v),dp(v-w[i])+c[i] );
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
intv,n,w[31]={},dp[200001]={},i,j;
while(~scanf("%d",&v))
{
scanf("%d",&n);
memset(dp,0,sizeof(dp));
for(i=0;i<n;++i)
{
scanf("%d",&w[i]);
for(j=v;j>=w[i];--j)
{
dp[j]=max(dp[j],dp[j-w[i]]+w[i]);
}
}
printf("%d\n",v-dp[v]);
}
return 0;
}