01背包

52 阅读2分钟

2. 01背包问题 - AcWing题库

image.png

解析

首先设置一个二维数组dp[i][j],令其表示前i个物品装进容量为j的背包能获得的最大价值.

dp[n][m]的值就是0-1背包问题的解.只考虑第i件物品时,将情况分为是否放入第i件物品两种:

  1. 对于容量为j的背包,如果已经无法放入第i件物品,那么这个问题就转化成将前i-1个物品放入容量为j的背包的问题即dp[i][j]=dp[i-1][j]
  2. 对于容量为j的背包,如果还能放入第i件物品,那么放它之后背包容积缩减为j-v[i],且已知这个物品的价值w[i],这个问题就转化成了将前i-1个物品放入容量为j-v[i]的背包的问题即dp[i][j]=dp[i - 1][j - v[i]] + w[i] 从这两种情况可以得到状态转移方程dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i])
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 1005;
int v[N];      // 体积
int w[N];      // 价值
int dp[N][N];  // dp[i][j],前i件物品,背包容量为j的情况下的能装物品的最大价值

int main() 
{
    int n, m;   
    scanf("%d%d",&n,&m); // n物品数量 m背包容积
    for(int i = 1; i <= n; i++) 
        scanf("%d%d",&v[i],&w[i]);

    for(int i = 1; i <= n; i++) 
        for(int j = 1; j <= m; j++)
        {
            //  剩余容量装不进第i个物品,则价值无法更新
            if(j < v[i]) 
                dp[i][j] = dp[i - 1][j];
            // 能装进去,则比较装/不装第i件物品,哪个价值更高
            else    
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]);
        }           
    printf("%d\n",dp[n][m]);
    return 0;
}