acwing 12 背包问题求具体方案

题面

在这里插入图片描述

题解

  1. 01背包问题求具体方案数,题目要求所选方案的字典序最小,我们看从1到n的物品中只有3中情况,只能选,则必须选;不能选,则必不选;可选可不选,则必须选,因为从前向后,前面选择的一定比后面的选择好
  1. 我们可以从后向前,求出当前背包的最大总价值就是 f[1][m]
  1. 再从第1个物品遍历到第n个物品,其中f[i][j]为当前最优情况,若满足

(1) f [ i ] [ j ] == f [ i + 1 ] [ j ] , 则表示f[ i ] [ j ] 是从f [ i + 1 ] [ j ] 状态转移过来的
(2) f [ i ] [ j ] == f [ i + 1 ] [ j - v [ i ] ] + w [ i ] , 则表示f [ i ] [ j ] 是从 f [ i + 1][j - v[i]]状态转移过来的

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 1010;

int n, m;
int w[N], v[N];
int f[N][N];

int main() {
    
    

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

    for (int i = n; i >= 1; i--) {
    
      //每个状态是从它后边更新过来的
        for (int j = 0; j <= m; j++) {
    
    
            f[i][j] = f[i + 1][j];
            if (j >= v[i]) {
    
    
                f[i][j] = max(f[i][j], f[i + 1][j - v[i]] + w[i]);
            }
        }
    }

    int j = m; // f[1][m]是最大值
    for (int i = 1; i <= n; i++) {
    
    
        if (j >= v[i] && f[i][j] == f[i + 1][j - v[i]] + w[i]) {
    
    
            cout << i << " ";
            j -= v[i];
        }
    }
    cout << endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44791484/article/details/115268104