背包问题最优方案数
问题 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;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战