01背包问题的解决 原文:Jiao机器感知8月7日

01背包问题解法1. 定义我们有$N$种物品,物品$i$的重量为$w[i]$,价格为$p[i]$。我们假定所有物品的重量和价格都是非负的,背包所能承受的最大重量

其实01背包问题的解决
原文:Jiao机器感知8月7日的问题并不复杂,但是又很多的朋友都不太了解,因此呢,今天小编就来为大家分享01背包问题的解决
原文:Jiao机器感知8月7日的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

我们有$N$ 件物品,物品$i$ 的重量为$w[i]$,价格为$p[i]$。我们假设所有物品的重量和价格都是非负的,背包能承受的最大重量W为。如果限制每项只能选择0或1,则该问题称为0-1背包问题。

2. 二维动态规划解法

二维动态规划实际上就是填一张表。表中的数值代表可以获得的最大总值。表格如下:

现在我们分析动态规划中的状态转换。假设当前要寻找的状态为table[i][j],其中$i$表示第$i$个物品,$j$表示当前背包容量。由于是01背包问题,即某一项只能选择或不选择,即目前有两种可能的最优解,即选择或不选择,对应的总值为:table[ i-1][j],表[i-1][j-w[i]]+v[i],解释如下:

当不选择第$i$项时,当前最大值与状态为$i-1$、容量为$j$时的最优解相同;当选择第$i$项时,当前最大值为状态$i-1$,但容量为$j-w[i]$,当其值为$v[i]时加上当前项的值$,可见该问题的状态转移方程如下:

表[i][j]=max(表[i-1][j],表[i-1][j-w[i]]+v[i])

有了这个状态转移方程,我们就可以编写程序了。示例程序如下:

//总重量

#定义W (18)

//总的东西

#定义N (7)

int表[N+1][W+1]={0};

int 值[N+1]={0, 12, 10, 8, 11, 14, 7, 9};

int 权重[N+1]={0, 4, 6, 5, 7, 3, 1, 6};

无效背包()

{

整数k,w;

对于(k=1;k=N;k++){

对于(w=1;w=W;w++){

if (权重[k] w) {

表[k][w]=表[k-1][w];

} 别的{

int value1=表[k-1][w-权重[k]] + value[k];

int value2=表[k-1][w];

如果(值1值2){

表[k][w]=值1;

01背包问题的解决原文:Jiao机器感知8月7日

} 别的{

表[k][w]=值2;

}

}

}

}

}

运行结果如下。对比网络图,我们可以看到结果是完全一样的:

3. 最优解回溯

通过上述方法可以找到背包问题的最优解,但是我们仍然不知道最优解由哪些商品组成。因此,我们需要根据最优解进行回溯,找出解的组成。根据填表时的规则,通过反推法可知:

一个。如果table[i][j]==table[i-1][j],说明第$i$项没有被选中,那么上一步就是table[i-1][的位置j] 地点;

b.如果table[i][j] !=table[i-1][j],则表示选择了第$i$个产品,然后根据table[i][j]=table[i-1] [j-w [i]] + v[i] 可以得到之前的位置为table[i-1][j-w[i]];

c.重复此操作,直到找到i=0。

示例代码如下:

无效show_track()

{

向量对int,int轨道;

int i=N,j=W;

而(i0){

if (表[i][j]==表[i-1][j]) {

我- ;

} 别的{

track.push_back(make_pair(i, j));

int w=权重[i];

j-=w;

我- ;

01背包问题的解决原文:Jiao机器感知8月7日

}

}

for (int i=0; itrack.size(); i++) {

cout track[i].first ‘ ‘;

}

}

4. 复杂度分析

根据程序分析,我们需要填写的表数量为$N*W$,所以时间复杂度和空间复杂度都是$O(N*W)$,因为必须遍历所有可能性才能得到最优解决方案,不像有序数组可以分成两部分什么的,所以时间复杂度无法优化,但是空间复杂度还是可以优化的,因为我们每次更新都只和前一时刻的状态有关,所以有不需要通过保留这么多时刻的状态,空间复杂度可以优化到$O(W)$。首先分析一下上一步的核心代码:

对于(w=1;w=W;w++){

对于(k=1;k=N;k++){

if (权重[k] w) {

表[k][w]=表[k-1][w];

} 别的{

int value1=表[k-1][w-权重[k]] + value[k];

int value2=表[k-1][w];

.

}

可以看到,在核心代码部分,每次更新都只与前一时刻的状态相关。对应于表,每次更新只与表中的一行数据相关。这就是为什么空间复杂度可以优化为$O(W)$的原因,如果简单的优化成下面的代码:

对于(w=1;w=W;w++){

对于(k=1;k=N;k++){

if (权重[k] w) {

表[w]=表[w];

} 别的{

//需要w前面的w-weight[k]处的值

int value1=表[w-权重[k] + 值[k];

int value2=表[w];

01背包问题的解决原文:Jiao机器感知8月7日

表[w]=.

}

上面的代码不会给出正确的结果,为什么?我们从左到右扫描行,需要取$w-weight[k]$,也就是$w$左边的值,但是我们从左边开始更新,那么我们需要的值就是初始更新被覆盖,得到的值是当前时刻的值,而不是上一时刻的期望值。显然,不可能得到正确的结果。为了避免这种覆盖现象,我们可以通过反向扫描的方式进行更新。即从右向左更新,这样更新的位置就不会被左边所需要,也能得到正确的结果。代码如下:

无效背包优化()

{

//只使用表中的第一行

整数k,w;

对于(k=1;k=N;k++){

对于(w=W;w=1;w–){

if (权重[k] w) {

表[0][w]=表[0][w];

} 别的{

int value1=table[0][w-weight[k]] + value[k];

int value2=表[0][w];

如果(值1值2){

表[0][w]=值1;

} 别的{

表[0][w]=值2;

}

}

}

}

}

5. 总结

01 背包问题的求解采用二维动态规划。简单二维动态规划的时间复杂度和空间复杂度都是$O(N*W)$。分析代码可以看出,状态转移时,当前状态只与前一时刻的状态相关,因此空间复杂度可以优化为$O(W)$。优化代码时需要注意的是:行更新顺序需要改变,以避免新的状态覆盖前一个状态。需要从右向左更新当前的状态;得到最优解后,需要回溯最优解。该方法步骤可以如上所述进行。

附录

用户评论

01背包问题的解决
原文:Jiao机器感知8月7日
在哪跌倒こ就在哪躺下

这个解释很清楚!我之前一直搞不懂01背包问题的解法,看完你的文章豁然开朗了!动态规划真是太牛逼了

    有10位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
十言i

作为一名计算机专业的学习者,对算法问题非常感兴趣。这篇关于01背包问题的文章讲解得比较全面,尤其是你提供的代码示例真的很 hilfreich !

    有8位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
别悲哀

这个解法确实有效,但是运行时间有点慢啊,有没有更快的解法?我这里需要处理的数据量比较大…

    有15位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
纯真ブ已不复存在

对于初学者来说可能有点难理解吧,算法模型的介绍可以用更通俗易懂的语言解释一下好吗?

    有5位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
軨倾词

文章写的不错,但为什么没有提到贪心算法这种解法呢?我觉得贪心算法在某些特殊情况下的效率更高。

    有18位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
凉城°

终于找到了解决01背包问题的思路!我已经开始尝试用代码实现它了,期待能够成功运行!感谢你的分享!

    有9位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
棃海

动态规划的思想的确很巧妙,但对于复杂程度更高的背包问题是否还有其他更优解法的存在呢?

    有12位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
浮光浅夏ζ

这个01背包问题的解法是我刚学到的算法之一,感觉有点抽象难以理解。请问是否有更加直观的方法来解释它?

    有20位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
安之若素

我很想尝试不同的解决方法,例如遗传算法或神经网络算法来求解01背包问题,不知道这有没有什么资源可以参考?

    有7位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
墨城烟柳

感觉代码实现太繁琐了,是不是有更简洁的解题思路呢?像一些基于图形化或者可视化的方法或许更容易理解?

    有5位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
高冷低能儿

写的很棒啊!我已经开始应用到我的个人项目中去了,你的解法有效率很高。感谢您的贡献!

    有5位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
恰十年

对于01背包问题来说,最优解应该是以最大价值为目标的吧?其他的目标函数如何定义呢?

    有13位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
浅巷°

感觉你的代码写得很专业啊!请问你是在哪种语言下编写的呢?是否可以分享更多关于编程方面的知识呢?

    有19位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
花花世界总是那么虚伪﹌

文章内容不错,但对于01背包问题的不同变体,比如带约束的背包问题,有没有什么更具体的解决方案介绍呢?

    有13位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
浮殇年华

我个人觉得动态规划这种解法还是比较耗时的,有没有一些其他的高效算法可以参考?例如使用树搜索或者分支限界法?

    有10位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
■□丶一切都无所谓

01背包问题是一个经典的组合优化问题,这篇博文对它的讲解很有针对性!学习到了很多新的知识点。

    有20位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
一纸愁肠。

感谢分享!这篇文章不仅清晰地描述了01背包问题的解法,还提供了具体的代码示例,非常实用!

    有20位网友表示赞同!

01背包问题的解决
原文:Jiao机器感知8月7日
短发

我还在尝试理解动态规划算法的原理,这篇博文对我的帮助很大,希望下次可以分享更多关于其他算法的讲解。

    有6位网友表示赞同!

原创文章,作者:小su,如若转载,请注明出处:https://www.sudun.com/ask/98496.html

Like (0)
小su的头像小su
Previous 2024年8月29日 下午8:43
Next 2024年8月29日 下午8:58

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注