Title

01背包方案计数

01背包方案计数

求装到一定容量的方案总数

\(N\)个物品,每个物品有重量 \(w_i\)和价值\(v_i\)

背包容量为 \(W\)

背包:每个物品要么选 1 次,要么不选。

问法:求恰好\(W\)的情况下,有多少种选物品的方案?

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
const int maxn = 2e5 + 5;

void solve()
{
    int n = 0, W = 0;
    std::cin >> n >> W;
    std::vector<int> w(n + 1, 0), v(n + 1, 0);
    std::vector<int> dp(W + 1, 0); dp[0] = 1;
    for (int i = 1; i <= n; i++)
    {
        for (int j = W; j >= w[i]; j--)
        {
            dp[j] += dp[j - w[i]];
        }
    }
    std::cout << dp[W] << endl;
}

signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr); std::cout.tie(nullptr);
    int _t = 1;
    // std::cin >> _t;
    while (_t--) solve();
    return 0;
}

求最优方案总数

\(f[i][j]\)为在只能放前\(i\)个物品的情况下,容量为\(j\)的背包正好装满所能达到的最大值
每一个\(dp\)状态用一个\(g[i][j]\)来表示方案数

转移方程:

如果
\([f_{i,j} = f_{i-1,j}]\)\([f_{i,j} \neq f_{i-1,j-v}+w]\) 说明我们此时不选择把物品放入背包更优,方案数由

\([g_{i-1,j}]\) 转移过来,

如果
\([f_{i,j} \neq f_{i-1,j}]\)\([f_{i,j} = f_{i-1,j-v}+w]\) 说明我们此时选择把物品放入背包更优,方案数由

\([g_{i-1,j-v}]\) 转移过来,

如果
\([f_{i,j} = f_{i-1,j}]\)\([f_{i,j} = f_{i-1,j-v}+w]\) 说明放入或不放入都能取得最优解,方案数由 \([g_{i-1,j}]\)\([g_{i-1,j-v}]\) 转移过来。

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
const int maxn = 2e5 + 5;

void solve()
{
    int n = 0, W = 0;
    std::cin >> n >> W;
    std::vector<int> w(n + 1, 0), v(n + 1, 0);
    std::vector<int> f(W + 1, 0), g(W + 1, 0);
    for (int i = 1; i <= n; i++)
    {
        for (int j = W; j >= w[i]; j--)
        {
            int tmp = std::max(f[j], f[j - w[i]] + v[i]);
            int c = 0;
            if (tmp == f[j]) c += g[j];
            if (tmp == f[j - w[i] + v[i]]) c += g[i - w[i]];
            f[j] = tmp; g[j] = c;
        }
    }
    int mx = 0;
    for (int i = 0; i <= W; i++) mx = std::max(mx, f[i]);
    int res = 0;
    for (int i = 0; i <= W; i++) if (dp[i] == mx) res += cnt[i];  
}

signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr); std::cout.tie(nullptr);
    int _t = 1;
    // std::cin >> _t;
    while (_t--) solve();
    return 0;
}
posted @ 2025-09-16 09:24  栗悟饭与龟功気波  阅读(5)  评论(0)    收藏  举报