背包问题最优方案数

问题 AJ: 【基础】背包问题求方案数

题目描述

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。
第 i 件物品的体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。

输出 最优选法的方案数。注意答案可能很大,请输出答案模 10+7的结果。

输入

第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。
数据范围
0<N,V≤1000
0<vi,wi≤1000

输出

输出一个整数,表示 方案数 模 10+7 的结果。

样例输入

4 5
1 2
2 4
3 4
4 6

样例输出

2

分析

求解最优方案的方案数,我们需要维护两个数组,一个数组记录最大价值,一个数组记录方案数,对于方案数的状态,不选物品i的状态是```cpp
if(dp[i][j] == dp[i-1][j]) g[i][j] += g[i-1][j]

选择物品`i`的状态是
```cpp
if(j >= v[i] && dp[i][j] == dp[i-1][j-v[i]]) g[i][j] += g[i-1][j]

方案总数是两种状态方案的和,因为可能出现选择和不选物品i的价值是一样的情况,所以使用的是+=

代码

const int N = 1e9 + 7;
int v[1005],w[1005];
int dp[1005][1005],g[1005][1005];
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    //
    // freopen("E:/Code/C++/untitled1/input.txt","r",stdin);
    // freopen("output.txt","w",stdout);

    int n,vol;
    cin >> n >> vol;
    f(i,1,n+1) cin >> v[i] >> w[i];
    g[0][0] = 1;                   // 初始化方案
    for(int i = 1;i <= n;++i)
        for(int j = 0;j <= vol;++j)
        {
            if(j>= v[i]) dp[i][j] = max(dp[i-1][j],dp[i-1][j-v[i]] + w[i]);
            else dp[i][j] = dp[i-1][j];
 
 
            if(dp[i][j] == dp[i-1][j]) g[i][j] = g[i-1][j] % N;

            if(j >= v[i] && dp[i][j] == dp[i-1][j-v[i]] + w[i]) 
                g[i][j] = (g[i-1][j-v[i]]%N + g[i][j]%N)%N;
        }

    cout << g[n][vol]%N;

}
posted @   bakul  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示