C++---knapsack model---finding the number of solutions for the knapsack problem (one algorithm per day 2023.3.26)

Note:
This question is an extended question of "Dynamic Programming - 01 Backpack" , and it is also an approximate question of "Knapsack Model - Finding a Specific Solution for Backpack Problem" .

Problem:
There are N items and a knapsack of capacity V. Each item can only be used once.
The i-th item has volume vi and value wi.
Solve which items to put into the backpack so that the total volume of these items does not exceed the capacity of the backpack and the total value is the largest. Output
The number of solutions for the optimal method . Note that the answer may be very large, please output the result of the answer modulo 109+7.

Input format
The first line contains two integers, N and V, separated by spaces, representing the quantity of items and the volume of the backpack respectively.
Then there are N lines, and each line has two integers vi, wi, separated by spaces, representing the volume and value of the i-th item respectively.

Output format
Output an integer, which represents the result of the program modulo 10^9+7.

Data range
0<N, V≤1000
0<vi, wi≤1000

输入:
4 5
1 2
2 4
3 4
4 6
输出:
2
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 1010, mod = 1000000007;
int n, m;                       //n为物品数量,m为背包体积
int v[N], w[N], f[N], g[N];     //v[i]第i个物品的体积,w[i]第i个物品的价值,f用来计算对于前i个物品,体积恰好为j时的最大价值,g用来计算对于前i个物品,体积恰好为j时取最大价值的方案数量。

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

    //初始化,计算体积恰好为j,就需要将f数组除了f[0][0]全部初始化为-INF(这样才能用max来进行转移),
    // 而g[0][0]需要初始化为1(前0个物品价值恰好为0的方案数为1)
    memset(f, -0x3f3f3f, sizeof f);
    f[0] = 0;
    g[0] = 1;
    //经典的一维双循环01背包
    for (int i = 1; i<=n; i++) {
    
    
        for (int j = m; j>=v[i]; j--) {
    
    
            int maxv = max(f[j], f[j-v[i]]+w[i]);   //先把本次的最大价值求出,以便后续判断g的三种情况
            int c = 0;
            if (maxv == f[j]) c += g[j];
            if (maxv == f[j-v[i]]+w[i]) c += g[j-v[i]];
            g[j] = c % mod;
            f[j] = maxv;
        }
    }

    int res = 0;    //由于求出的是体积恰好为j时的最优方案,而不是最多为j的最优方案,所以需要把f[0~m]都看一遍求出最大价值。
    for (int i = 0; i<=m; i++) res = max(res, f[i]);
    int cnt = 0;    //再拿最大价值去求方案数(因为最大价值可能有多个,那就把所有能达到最大价值的方案全部计算)
    for (int i = 0; i<=m; i++) {
    
    
        if (f[i] == res) cnt = (cnt+g[i])%mod;
    }

    cout << cnt;
    return 0;
}

Idea:
This question requires finding the number of optimal solutions , so you can’t push back like finding specific solutions, because there may be multiple optimal solutions, so if you want to calculate the optimal number of solutions, you need to calculate the optimal solution first. Find the solution, and then calculate how many solutions can be transferred to the optimal solution.

Classic y-style dp method:
1. State calculation

f[i][j] : For all the schemes when the volume of the first i items is exactly j, the attribute is Max.
g[i][j]: For the first i items, the number of solutions with the maximum value when the volume is exactly j, the attribute is Count.

2. State transfer
First of all, f[i][j]there is nothing to say, it is the transfer method of 01 backpack (judging whether to select item i/not to select item i)
f[i][j] = max(f[i-1][j], f[i-1][j-v]+w)

Then g[i][j], consider three situations:
the number of schemes c = 0,
1. If f[i][j]the (maximum value) at this time is f[i-1][j]transferred from , then c += g[i-1][j]
2. If at this time f[i][j], is f[i-1][j-v]+wtransferred from , then c += g[i-1][j-v]
3. If it is f[i][j]possible Transfer from two situations at the same time, then c = (g[i-1][j] + g[i-1][j-v])
g[i][j] = c, you can find this transfer.

If it is helpful, please give a free like~ Someone watching is the motivation to support me to write down!

Disclaimer:
The source of the algorithm idea is Mr. Y. For details, please refer to https://www.acwing.com/
This article is only used for learning records and exchanges

Guess you like

Origin blog.csdn.net/SRestia/article/details/129777856