多重背包

多重背包,,嗯???怎么和完全背包那么像???

完全一个物品可以选k次,完全有限次的(s+1次选法),就是这个这个区别么???

可能不是一样的吧?我的原理好像弄的不是很清楚,知道看到了这位大佬发的:

************************************************************************************************************************

我感觉多重背包还是应该理解为01背包的扩展,完全背包的“无穷性”导致了跟这俩背包的性质完全不同,特别是完全背包推导那个表达式的时候:
因为
f[i][j]=max(f[i-1][j],f[i-1][j-v]+w,f[i-1][j-2v]+2w,...)
f[i][j-v]=max(f[i-1][j-v],f[i-1][j-2v]+w,...)
又因为物品无穷性,所以上面两式有一一对应的关系
所以
f[i][j]=max(f[i-1][j],f[i][j-v]+w)

这是01背包和多重背包的“有限性”都推导不出的结论~

**************************************************************************************************************************

01背包是每个物品枚举选0个还是1个,多重背包是枚举选0个,1个,2个……

问题二:

怎么样判读从小到大,什么时候判断从大到小;

如果不压缩空间,那么什么顺序都可以。如果压缩了空间,选择的循环顺序要保证代码和压缩前是等价的。比如如果状态计算是f[i, j] = max(f[i - 1, j], f[i - 1, j - v] + w,那么只能从大到小循环,否则计算j时,j - v会先被计算,那么其实算的就是f[i, j] = max(f[i - 1, j], f[i], j - v] + w了,不等价。

这是y总的回答,看完之后我悟了!!!懂了!!!

有 NN 种物品和一个容量是 VV 的背包。

第 ii 种物品最多有 sisi 件,每件体积是 vivi,价值是 wiwi。

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

输入格式

第一行两个整数,NVN,V,用空格隔开,分别表示物品种数和背包容积。

接下来有 NN 行,每行三个整数 vi,wi,sivi,wi,si,用空格隔开,分别表示第 ii 种物品的体积、价值和数量。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V1000<N,V≤100
0<vi,wi,si1000<vi,wi,si≤100

输入样例

4 5
1 2 3
2 4 1
3 4 3
4 5 2

输出样例:

10
这个数据范围不是很大,100,第一种做法就是暴力啊,原来的完全背包的开始思路也是暴力,不过那题的数据范围太大了,y总选择了优化
复制代码
#include<iostream>
using namespace std;
const int N=110;
int n,m;
int f[N][N],v[N],w[N],s[N];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>v[i]>>w[i]>>s[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++)
        {
            for(int k=0;k<=s[i]&&k*v[i]<=j;k++)
            {
                f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
            }
        }
    }
    cout<<f[n][m]<<endl;
    return 0;
}
复制代码

因为多重背包是01背包的扩展,我看到有直接把完全背包拆成01背包来写的

不吹牛逼,说实话我刚开始学的时候一直把多重背包和完全背包联系起来,导致刚开始拆的时候并没有明白具体意思

但我现在明白了。

就是把后面的s全部化为1,分开来看,比如:

2  5  2

3  1  3

1  1  2

就这个,可以看成:

2  5

2  5

3  1

3   1

3   1

1   1

1   1

懂我意思了吧,嘻嘻

然后这么硬拆虽然暴力血腥,但...不得不说,我喜欢......

复制代码
#include<iostream>
using namespace std;
const int N=1e6;
long long int f[N],v[N],w[N];
int main(){
    int n,m,a,b,c;
    cin>>n>>m;
    int t=1;
    for(int i=1;i<=n;i++)
    {
        cin>>a>>b>>c;
        for(int j=1;j<=c;j++)
        {
            v[t]=a;
            w[t]=b;
            t++;
        }
    }
    for(int i=1;i<=t;i++)
    {
        for(int j=m;j>=v[i];j--)
        {
            f[j]=max(f[j],f[j-v[i]]+w[i]);
        }
    }
    cout<<f[m]<<endl;
    return 0;
}
复制代码

 

优化成一维,这个我也喜欢,嘻嘻嘻:

(因为y总的j,k的下标我摸不清头脑为什么从0开始,我不理解...)

复制代码
#include<iostream>
using namespace std;
const int N=110;
int f[N],v[N],w[N],s[N];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>v[i]>>w[i]>>s[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=m;j>=0;j--)
        {
            for(int k=1;k<=s[i];k++)
            {
                if(j>=k*v[i])
                    f[j]=max(f[j],f[j-k*v[i]]+k*w[i]);
            }
        }
    }
    cout<<f[m]<<endl;
    return 0;
}
复制代码

 

posted @   小志61314  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示