原题
01背包问题
有n个重量和价值分别为wi,vi的物品。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。
1<=n<=100
1<=wi,vi<=100
1<=W<=10000
样例输入
n=4
(w,v)={(2,3),(1,2),(3,4),(2,2)}
W=5
样例输出
7(选择0、1、3号物品)
代码
递归写法(记忆化搜索)
int n,W;
int w[MAX_N],v[MAX_N]
//记忆化数组
int dp[MAX_N+1][MAX_N+1];
//从第i个物品开始挑选总重小于j的部分
int rec(int i,int j)
{
if(dp[i][j]>=0)
{
return dp[i][j];
}
int res;
if(i==n)
{
//没有剩余物品
res=0;
}
else if(j
递推写法(逆向进行)
dp[i][j]定义为从第i个物品开始挑选总重小于j的部分
dp[n][j]=0
dp[i][j]= dp[i+1][j] (j
dp[i][j]= max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]) (j>=w[i])
int n,W;
int w[MAX_N],v[MAX_N]
//DP数组
int dp[MAX_N+1][MAX_N+1];
void solve()
{
for(int j=0;j<=W;j++)
{
dp[n][j]=0;
}
for(int i=n-1;i>=0;i--)
{
for(int j=0;j<=W;j++)
{
if(j
递推写法(正向进行)
dp[i+1][j]定义为从前i个物品中选出总重量不超过j的物品时总价值的最大值
dp[0][j]=0
dp[i+1][j]=dp[i][j]
(j
dp[i+1][j]=max(dp[i][j],dp[i][j-w[i]]+v[i]) (j>=w[i])
int n,W;
int w[MAX_N],v[MAX_N]
//DP数组
int dp[MAX_N+1][MAX_N+1];
void solve()
{
for(int j=0;j<=W;j++)
{
dp[0][j]=0;
}
for(int i=0;i
状态转移
从“前i个物品中选取总重不超过j时的状态”向“前i+1个物品中选取总重不超过j”和“前i+1个物品中选取总重不超过j+w[i]时的状态”的转移。
int n,W;
int w[MAX_N],v[MAX_N]
//DP数组
int dp[MAX_N+1][MAX_N+1];
void solve()
{
memset(dp,0,sizeof(dp));
for(int i=0;i
注:文章内容源于《挑战程序设计竞赛》(第二版)