HDU 2955中dp【j】表示偷取价值j不被抓的最大的概率,
那么对于01背包而言,同样可以用dp【j】表示拿去价值j时所需要的背包的最小体积。
状态转移方程dp【j】 = min{dp【j】,dp【j-value【i】+weight【i】}
但是这种方法的缺点是,只能计算背包value比较小的情况,如果value比较大那么,dp【j】这个数组就会很大,而且时间复杂度和背包的value之和有关。
这种方法的优点就是,可以计算背包weight比较大的情况,而用dp【i】表示体积为i的背包所得的最大的价值就不可以,原因同上。
具体选择哪一种,需要跟具体以,看看用哪种方法的表示状态比较清晰,还要权衡value和weight的大小。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include <iostream>
#include<string>
#include <queue>
#include <stack>
#include <vector>
#define MAXN 100005
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define INF 99999
using namespace std;
int main()
{
int v;//体积
int value[MAXN];///价值
int weight[MAXN];///所占体积
int n;///物品件数
int dp[MAXN];///dp[i]表示装入价值为i是所需要的背包的最小体积
cin>>v>>n;
int sum = 0;
for(int i=0;i<n;i++)
{
cin>>weight[i]>>value[i]; //输入体积,价值
sum += value[i];
}
//cout<<" "<<sum<<endl;
for(int i=0;i<=sum;i++)///赋初值,表示没有物品时,除了0,其他的情况赋值为v+1,表示均不可能,
{ ///因为最后是这么筛选的if(dp[j]<=v)所以赋值为v+1就可表示为不可能。
dp[i] = v+1;
}
dp[0] = 0;
for(int i=0;i<n;i++)
for(int j=sum;j>=0;j--)
{
dp[j] = min(weight[i]+dp[j-value[i]],dp[j]);
}
for(int j=sum;j>=0;j--)
{
if(dp[j]<=v)
{
cout<<j<<endl;
//cout<<dp[j]<<endl;
break;
}
}
}