2022.10.16 14:00左右 破百赞
2023.7.5 14:00左右 破二百赞
2022.11.16 22:09 写出多包II的题解链接
请大家点个赞,有写的不好的可以在评论区评论
题目描述
有 $N$ 种物品和一个容量是 $V$ 的背包。
第 $i$ 种物品最多有 $s_{i}$ 件,每件体积是 $v_{i}$,价值是 $w_{i}$。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
输入格式
第一行两个整数,$N$,$V$,用空格隔开,分别表示物品种数和背包容积。
接下来有 $N$ 行,每行三个整数 $v_{i},w_{i},s_{i}$,用空格隔开,分别表示第 $i$ 种物品的体积、价值和数量。
输出格式
输出一个整数,表示最大价值。
数据范围
$0<N,V≤100$
$0<v_{i},w_{i},s_{i}≤100$
样例
输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
输出样例:
10
分析
当 $s_{i} = 1$ 时,相当于01背包中的一件物品
当 $s_{i} > 1$ 时,相当于01背包中的多个一件物品
故我们可以死拆(把多重背包拆成01背包)
别忘了点赞
C++ 代码
#include <bits/stdc++.h>
using namespace std;
int a[10005],b[10005],t=0,n,m,dp[10005]={ },w,v,s;
int main()
{
cin>>n>>m;
while(n--)
{
cin>>v>>w>>s;
while(s--)
{
a[++t]=v;
b[t]=w;
}//死拆,把多重背包拆成01背包
}
for(int i=1;i<=t;i++)
for(int j=m;j>=a[i];j--)
dp[j]=max(dp[j-a[i]]+b[i],dp[j]);//直接套01背包的板子
cout<<dp[m]<<endl;
return 0;
}
update:2022.10.16 18:06 优化,稍微短了一点(把for改成while)(
saber简化代码
#include <bits/stdc++.h>
using namespace std;
int dp[1005],n,t,v,w,s;
main()
{
cin>>n>>t;
while(n--)
{
cin>>w>>v>>s;
while(s--)
for(int j=t;j>=w;j--)
dp[j]=max(dp[j],dp[j-w]+v);
}
cout<<dp[t];
}
其实那个死拆还有后面的01背包不用分开吧?当成s个物品做就可以了。
分开的话能更好的理解
ok
good
老哥代码真好,但是没看懂,还能具体一点吗
就是有s个就做s次01背包嘛
《9年级的神犇》
好贴心 还为saber玩家考虑了 必须点赞啊
啥是saber哇
打挑战的,需要代码少这样写起来快
我非常想说这种想法非常适合我这种不太懂的变通的娃,orz
$好耶好耶 (^-^)V $
爆赞
用三重循环也可以
看到死拆就笑了,大哥牛皮
泰裤辣
nb
wc太diao了
好喜欢这种符合猪脑子体制的代码 dei佬Orz
可以2进制拆分
第一次在acwing上点赞,写的好!
这个是二维的,差一个数据,不过应该容易理解
%%%%%
%%%
啥是saber,有无大佬解释一下
打挑战的,需要代码少这样写起来快
想问一下,当前容量不够时,f[i][j]=f[i-1][j]这行代码体现在哪里?
体现在for循环max里面,01背包是从满容量开始到v[i]进行循环,dp数组默认全部是0 ,也就是说当第一个n-v[i]出现的时候状态方程才更新,也就是放物品