背包九讲
一 01背包:
一件物品只能放一次
二维动态转移方程 dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])
降低空间复杂度用一维: dp[j] = max(dp[j],dp[j-w[i]]+v[i]), j 从V到0(为了防止数组越界,到w[i])
代码实现:
#include<algorithm> using namespace std; const int MAX = 100; int dp[MAX],w[MAX],v[MAX]; int n,m; int main() { scanf("%d%d",&n,&m); for(int i = 1; i <= n ; i++){ scanf("%d%d",&w[i],&v[i]); } for(int i = 1; i <= n ; i++){ for(int j = m; j >= w[i]; j--){ dp[j] = max(dp[j],dp[j-w[i]]+v[i]); } } printf("%d ",dp[m]); return 0; }
二 完全背包:
一件物品能放无限次
二维动态转移方程 dp[i][j] = max(dp[i-1][j],dp[i][j-w[i]]+v[i])
降低空间复杂度用一维:dp[j] = max(dp[j],dp[j-w[i]]+v[i]),不过j从0到V(为了防止数组越界,从w[i]开)
也可以看做m/(w[i])个物品,继续看成01背包问题,价值和重量都放大2^k次
代码实现:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAX = 100; int dp[MAX],w[MAX],v[MAX]; int n,m; int main() { scanf("%d%d",&n,&m); for(int i = 1; i <= n ; i++){ scanf("%d%d",&w[i],&v[i]); } for(int i = 1; i <= n ; i++){ for(int j = w[i]; j <= m; j++){ dp[j] = max(dp[j],dp[j-w[i]]+v[i]); } } printf("%d ",dp[m]); return 0; }