快3网上购买

【动态规划】01背包问题【续】

电脑杂谈  发布时间:2019-10-07 19:04:19  来源:网络整理

01背包动态规划算法_复杂网络小世界特性,无尺 度特性及高聚类系数_动态规划01背包复杂度

这段时间一天上班,确实没有整块的时间来写博客了,一不小心就到周末了,要是不写篇博客,那就又要鸽了。为了不打脸,还是加班加点的把这篇博客给写了起来。

20190323214213.png

再说个题外话,最近经常在看一本关于Mysql的掘金小册,感觉很棒,作者用通俗易懂的语言将Mysql的底层原理进行了介绍,图文并茂,讲解的很深入,可以看出作者必须是花了不少心思,借阅了不少书籍的。据说作者是个95后,为了写这本小册子还特意辞了职,简直优秀!

20190323215229.png

快3网上购买一篇文章一般应该花费40~60分钟,建议花整块的时间进行阅读。

01背包动态规划算法_动态规划01背包复杂度_复杂网络小世界特性,无尺 度特性及高聚类系数

从作者的身上,也发现了一种匠心精神,反观自己动态规划01背包复杂度快3网上购买,写这样水的文章,实在是感慨。所以决定对文章质量把把关,本着宁缺毋滥的方法来写作,尽量不耽误你们的时间。

好了,闲话就说到这了,言归正传。

上一篇中,我们知道了01背包问题,并用三种方式进行了求解,但毕竟在最终一种解法上,我们能够再对它的空间复杂度进行改进。

已经过去一个星期了,可能一部分人终于忘记了之前的解题策略,所以在这里把之前填表法使用到的图贴了回来:

复杂网络小世界特性,无尺 度特性及高聚类系数_动态规划01背包复杂度_01背包动态规划算法

这是我们上一篇填表法的最后结果,在这里,聪明的你需要能看到,其实这儿大部分的内容都没有用上,那么让我们来想想,如何改进一下空间复杂度呢?

再回头看下之前的递推关系式:

可以发现,每次求解 KS(i,j)只与KS(i-1,m) {m:1...j} 有关。也就是说,如果我们了解了K(i-1,1...j)就显然能求出KS(i,j),为了更直观的理解,再画一张图:

复杂网络小世界特性,无尺 度特性及高聚类系数_01背包动态规划算法_动态规划01背包复杂度

下一层只应该按照上一层的结果就能推出答案,举个栗子,看i=3,j=5时,在求这个子问题的最优解时,根据上述计算公式,KS(3,5) = max{KS(2,5),KS(2,0) + 3} = max{6,3} = 6;如果我们得到了i=2时所有子问题的解,那么就很容易求出i=3时所有子问题的解。

因此,我们可以将求解空间进行改进,将二维数组压缩成一维字符,此时,装填转移方程变为:

KS(j) = max{KS(j),KS(j - wi) + vi}

这里KS(j - wi)就相当于原来的KS(i-1, j - wi)。需要注意的是,由于KS(j)是由它上面的KS(m){m:1..j}推导下来的,所以在第二轮循环扫描的过后需要由后往后进行计算,因为一旦由前往后推导的话,前一次循环保存出来的值可能会被设置,从而导致错误。

快3网上购买这么说也许还是不太清楚,回头看上面的图,我们从i=2推算i=3的子问题的解时,此时一维数组中存放的是{0,0,2,4,4,6,6,6,6,6,6},这是i=2时所有子问题的解,如果我们以前往后计算i=3时的解,比如,我们计算KS(0) = 0,KS(1) = KS(1) = 0 (因为j=1时,装不下第三个珠宝,第三个珠宝的重量为5),KS(2) = 2,KS(3) = 4,KS(4) = 4, KS(5) = max{KS(5), KS(5-5) + 3} = 6,....,KS(8) = max{KS(8),KS(8 - 5) + 3} = 7。在这里计算KS(8)的之后,我们就把以前KS(8)的内容设置掉了,这样,我们后续计算就能够找到这个位置的原值(这个栗子没举好。。因为前面的计算没有用到KS(8)= =),也就是上一轮循环中计算下来的值了,所以在遍历的过后,需要从后往后进行倒序遍历。

复杂网络小世界特性,无尺 度特性及高聚类系数_动态规划01背包复杂度_01背包动态规划算法

public class Solution{
    int[] vs = {0,2,4,3,7};
    int[] ws = {0,2,3,5,5};
    int[] newResults = new int[11];
    @Test
    public void test() {
        int result = ksp(4,10);
        System.out.println(result);
    }
    private int ksp(int i, int c){
        // 开始填表
        for (int m = 0; m < vs.length; m++){
            int w = ws[m];
            int v = vs[m];
            for (int n = c; n >= w; n--){
                newResults[n] = Math.max(newResults[n] , newResults[n - w] + v);
            }
            // 可以在这里输出中间结果
            System.out.println(JSON.toJSONString(newResults));
        }
        return newResults[newResults.length - 1];
    }
}

输出如下:

[0,0,0,0,0,0,0,0,0,0,0]
[0,0,2,2,2,2,2,2,2,2,2]
[0,0,2,4,4,6,6,6,6,6,6]
[0,0,2,4,4,6,6,6,7,7,9]
[0,0,2,4,4,7,7,9,11,11,13]
13

这样,我们就成功将空间复杂度从O(n*c)优化到了O(c)。当然,空间改进的损失是,我们只好知道最终的结果,但能够再回溯中间的选取,也就是无法按照最后结果来找到我们要选的物品组合。

01背包问题通常有两种不同的问法,一种是“恰好装满背包”的最优解,要求背包应该装满,那么在初始化的之后,除了KS(0)为0,其他的KS(j)都需要设置为负无穷大,这样就可以确保最后受到的KS(c)是正好装满背包的最优解。另一种问法不要求装满,而是只期望最终受到的价值尽可能大,那么初始化的之后,应该将KS(0...c)全部设置为0。

为什么呢?因为初始化的泛型,实际上是在没有任何物件可以放在背包的状况下的合法状态。如果规定背包正好装满,那么这时唯有容量为0的背包可以在哪个都不装且价值为0的状况下被“恰好装满”,其他容量的背包均没有合法的解,因此属于未定义的状况动态规划01背包复杂度,应该设定为负无穷大。如果背包不需要被装满,那么任何容量的背包都有合法解,那就是“什么都不装”。这个解的价值为0,所以初始状况的值都是0。

01背包问题可以用自上而下的卷积记忆法求解,也可以用自下而上的填表法求解,而后者可以将二维数组的解空间优化成一维数组的解空间,从而推动空间复杂度的改进。

对于01背包问题的两种不同问法,实际上的差别便是初始值设定不一样,解题策略是一样的。


本文来自电脑杂谈,转载请注明本文网址:
http://www.kadakong.com/a/jisuanjixue/article-125493-1.html

    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    六合开奖网址 北京赛车PK10计划 恒彩彩票开户 快3平台 湖南福彩网 山东11选5 快三平台 快三在线投注 万发彩票注册 快三在线投注