0-1 背包问题及动态规划题解

发布时间:

1. 题目介绍

有 N 件物品和一个容量为 V 的背包,每件物品有各自的价值且只能被选择一次,要求在有限的背包容量下,装入的物品总价值最大。

「0-1 背包」是较为简单的动态规划问题,也是其余背包问题的基础。

动态规划是不断决策求最优解的过程,「0-1 背包」即是不断对第 i 个物品做出决策,「0-1」正好代表不选与选两种决定。


2. 题解代码(C++)

2.1 版本1:二维数组

  • 状态 f[i][j] 定义:前 i 个物品,背包容量 j 下的最优解(最大价值)。
  • 递推关系:
    • 如果当前背包容量 j 不够装第 i 件物品,则 f[i][j] = f[i-1][j]
    • 否则 f[i][j] = max(f[i-1][j], f[i-1][j - v[i]] + w[i])
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1005;
int v[MAXN];    // 体积
int w[MAXN];    // 价值
int f[MAXN][MAXN];  // f[i][j] 表示前 i 个物品,容量为 j 的最大价值

int main() {
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        cin >> v[i] >> w[i];

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) {
            if(j < v[i])
                f[i][j] = f[i-1][j];
            else
                f[i][j] = max(f[i][j], f[i-1][j - v[i]] + w[i]);
        }

    cout << f[n][m] << endl;
    return 0;
}

2.2 版本2:一维数组优化

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1005;
int v[MAXN];    // 体积
int w[MAXN];    // 价值
int f[MAXN];    // f[j] 表示容量为 j 的最大价值

int main() {
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        cin >> v[i] >> w[i];

    for(int i = 1; i <= n; i++)
        for(int j = m; j >= v[i]; j--) {
            f[j] = max(f[j], f[j - v[i]] + w[i]);
        }

    cout << f[m] << endl;
    return 0;
}

3. 总结

0-1背包问题是动态规划的经典入门题目,通过状态转移方程可以很好地理解动态规划的思想。二维版本更直观,一维版本更高效。