完全背包从01背包演化而来:
dp[i][j]背包空间为j时前i件物品
一式:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i],dp[i-1][j-2*w[i]]+2*v[i],,,,dp[i-1][j-n*w[i]]+n*v[i])
不放 , 放一件 ,放两件 ,,, 放n件
二式:dp[i][j-w[i]]=max(dp[i-1][j-w[i]],dp[i-1][j-2*w[i]]+v[i],dp[i-1][j-3*w[i]]+2*v[i],,,,,,, dp[i-1][j-n*w[i]]+ (n-1)*v[i])
假设背包空间为j-w[i] 得到dp[i][j-w[i]]的表达式, 两边再同时加上v[i] 得到三式:
三式: dp[i][j-w[i]]+v[i]=max(dp[i-1][j-w[i]]+v[i],dp[i-1][j-2*w[i]]+2*v[i],dp[i-1][j-3*w[i]]+3*v[i],,,, ,,, dp[i-1][j-n*w[i]]+n*v[i])
用三式替代一式中的 max 括号内后n项
即dp[i-1][j-w[i]]+v[i],dp[i-1][j-2*w[i]]+2*v[i],,,,dp[i-1][j-n*w[i]]+n*v[i]
得到状态转移方程:
dp[i][j]=max(dp[i-1][j],dp[i][j-w[i]]+v[i])
代码:
#include <iostream>
using namespace std;
int dp[100][100];
int main ()
{
// freopen("in.txt","r",stdin);
int n;
int weight;
cin>>n>>weight;
int w[n+1];
int v[n+1];
int i,j;
for(i=1;i<=n;i++)
{
cin>>w[i]>>v[i];
}
/*
4 5
1 2
2 4
3 4
4 5*/
for(i=1;i<=n;i++)
{
for(j=1;j<=weight;j++)
{
if(j<w[i])
{
dp[i][j]=dp[i-1][j];
}
else
{
dp[i][j]=max(dp[i-1][j],dp[i][j-w[i]]+v[i]);
}
}
}
cout<<dp[n][weight];
return 0;
}
输入:
2 11
2 3
6 14
输出:20