背包问题(01背包,完全背包,多重背包)

转自:http://www.cnblogs.com/daoluanxiaozi/archive/2012/05/06/2486105.html

背包问题,经典有背包九讲

01背包

不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前.

死亡骑士:"我要买道具!"

地精商人:"我们这里有三种道具,血瓶150块一个,魔法药200块一个,无敌药水350块一个."

死亡骑士:"好的,给我一个血瓶."

说完他掏出那张N元的大钞递给地精商人.

地精商人:"我忘了提醒你了,我们这里没有找客人钱的习惯的,多的钱我们都当小费收了的,嘿嘿."

死亡骑士:"......你妹"

死亡骑士想,与其把钱当小费送个他还不如自己多买一点道具,反正以后都要买的,早点买了放在家里也好,但是要尽量少让他赚小费.

现在死亡骑士希望你能帮他计算一下,最少他要给地精商人多少小费.

上面就是一个01背包问题。上面的问题可以描述为:

有n个物品,每个物品的重量为weight[i],每个物品的价值为value[i]。现在有一个背包,它所能容纳的重量为total,问:当你面对这么多有价值的物品时,你的背包所能带走的最大价值是多少?

思路:每个物品无非是装入背包或者不装入背包,那么就一个一个物品陆续放入背包中。可以有

tab[i][j] = max(tab[i-1][j-weight[i]]+value[i],tab[i-1][j]) ({i,j|0<i<=n,0<=j<=total})

其中i表示放第i个物品,j表示背包所容纳的重量,那么tab[i-1][j-weight[i]]+value[i]表示放入第i物品,刚开始接触会有疑问,tab[i-1][j-weight[i]]这个值,可以这样理解:tab[i-1][j]为装到上一个物品在背包j容量时的最佳值,那么如果我要求在j容量的时候放入现在的i物品的价值,那么是不是要先得到容量为(j-weight[i])时候的价值,即先得到 tab[i-1][j-weight[i]] ,所以 tab[i-1][j-weight[i]]+value[i] 为放入第i物品的价值; tab[i-1][j] 就是不放入第i个物品。

动态规划的思维就在这里体现了,即tab[i-1][j]是tab[i][j]的最优解(我觉得上面的思路讲解较容易理解)。

例子:5个物品,(重量,价值)分别为:(5,12),(4,3),(7,10),(2,3),(6,6)。


背包容量


0


1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


5物品


0


0


0


0


0


0


6


12


12


15


15


18


22


22


25


25


4物品


0


0


3


3


3


3


3


12


12


15


15


18


22


22


25


25


3物品


0


0


0


0


0


0


0


12


12


15


15


15


22


22


22


22


2物品


0


0


0


0


3


12


12


12


12


15


15


15


15


15


15


15


1物品


0


0


0


0


0


12


12


12


12


12


12


12


12


12


12


12

故有:

for i=[weight[0],total]

    tab[n-1][i] = weight[0];    //    n为物品数量

for i=[1,n)

    for j=[weight[i],total]

        tab[n-i-1][j] = max(tab[n-i][j-weight[i]]+value[i],tab[n-i][j])

    /*    print tab[0][total]    */

完全背包

不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前.

死亡骑士:"我要买道具!"

地精商人:"我们这里有三种道具,血瓶150块无限个,魔法药200块无限个,无敌药水350块无限个."

死亡骑士:"好的,给我一个血瓶."

说完他掏出那张N元的大钞递给地精商人.

地精商人:"我忘了提醒你了,我们这里没有找客人钱的习惯的,多的钱我们都当小费收了的,嘿嘿."

死亡骑士:"......你妹"

死亡骑士想,与其把钱当小费送个他还不如自己多买一点道具,反正以后都要买的,早点买了放在家里也好,但是要尽量少让他赚小费.

现在死亡骑士希望你能帮他计算一下,最少他要给地精商人多少小费.

上面的魔兽场景描述跟上面的只有小小的差异,就是物品有一个变为了无限个,这就是完全背包问题。完全背包问题可以描述为:

有n种物品,每种物品有无限个,每个物品的重量为weight[i],每个物品的价值为value[i]。现在有一个背包,它所能容纳的重量为total,问:当你面对这么多有价值的物品时,你的背包所能带走的最大价值是多少?

有了上面01背包的式子,这题会变的容易理解很多,只是这个式子要有小小的改动。01背包在二维数组上操作,就是为了防止一个物品被放入多次的情况。因此一维数组可以满足完全背包的问题。如下:

tab[j] = max(tab[j-weight[i]]+value[i],tab[j]);({i,j|0<i<=n,0<=j<=total})

根本就是一样的,只不过物品可以被放多次。


背包容量


0


1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


i物品


X


X


X


X


X


X


X


X


X


X


X


X


X


X


X


X

故有:

for i=[0,n)

    for(j=weight[i]; j<=total; j++)

        tab[j] = max(tab[j-weight[i]]+value[i],tab[j])

/*    print tab[0][total]    */

多重背包

不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前.

死亡骑士:"我要买道具!"

地精商人:"我们这里有三种道具,血瓶150块a个,魔法药200块b个,无敌药水350块c个."

死亡骑士:"好的,给我一个血瓶."

说完他掏出那张N元的大钞递给地精商人.

地精商人:"我忘了提醒你了,我们这里没有找客人钱的习惯的,多的钱我们都当小费收了的,嘿嘿."

死亡骑士:"......你妹"

死亡骑士想,与其把钱当小费送个他还不如自己多买一点道具,反正以后都要买的,早点买了放在家里也好,但是要尽量少让他赚小费.

现在死亡骑士希望你能帮他计算一下,最少他要给地精商人多少小费.

上面的魔兽场景描述跟上面的又有了小小的差异,就是物品有一个变为了有限个,问题也就变成了多重背包问题。

有n种物品,每种物品有amount[i]个,每个物品的重量为weight[i],每个物品的价值为value[i]。现在有一个背包,它所能容纳的重量为total,问:当你面对这么多有价值的物品时,你的背包所能带走的最大价值是多少?

多重和完全更接近,多了数量的限制,用一个count[n]计数数组来限制物品i的数量。当放入第i个物品是较优值的时候,count[i]=count[j-weight[i]]+1(j 的含义请查看代码);这样做是因为,放入第i个物品的操作是基于count[j-weight[i]]放入的,所以当count[i-weight[i]]>=amount[i]时,就要阻止放入即便放入第i个物品是较优值。 故有:

for i=[0,n)

    /*    将count数组清零        */

    for(j=weight[i]; j<=total; j++)

        if    count[j-weight[i]]<amout[i]

            tab[j] = max(tab[j-weight[i]]+value[i],tab[j]);

            if    tab[j]=tab[j-weight[i]]+value[i]    //    决定放入i是较优解

                count[i] = count[j-weight[i]] + 1

        else    if    tab[j]=0        //    防止装第1个物品和装其他物品的情况

            tab[j] = tab[j-1],count[j] = count[j-1]

        else    count[j] = count[j-1]

/*    print tab[0][total]    */

时间: 2024-10-23 01:31:50

背包问题(01背包,完全背包,多重背包)的相关文章

01、完全、多重背包模板

背包问题: 背包总容量为W,有n件重量为weight[i],权值为value[i]的物品 1.01背包: 这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放. 1 void ZeroOnePack (int weight,int value) 2 { 3 for (int w = W; w >= weight; w--) 4 dp[w] = max(dp[w - weight] + value, dp[w]); 5 } 2.完全背包: 每件物品有无限多个. void Complet

背包问题入门(单调队列优化多重背包

背包问题 写这篇文章主要是为了帮帮新人吧,dalao勿喷.qwq 一般的背包问题问法 每种物品都有一个价值w和体积c.//这个就是下面的变量名,请看清再往下看. 你现在有一个背包容积为V,你想用一些物品装背包使得物品总价值最大. 01背包 多种物品,每种物品只有一个.求能获得的最大总价值. 我们考虑是否选择第i件物品时,是需要考虑前i-1件物品对答案的贡献的. 分析 如果我们不选择第i件物品,那我们就相当于是用i-1件物品,填充了体积为v的背包所得到的最优解. 而我们选择第i件物品的时候,我们要

51nod 1086 背包问题 V2(二进制优化多重背包)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1086 题解:怎么用二进制优化多重背包,举一个例子就明白了. 如果要放n个苹果,可以将n个苹果分成几个2的次方1,2,3,4,m^2然后n可以由这些按照某种组合来组合. 于是就知道怎么优化了. #include <iostream> #include <cstring> #include <cstdio> using namespac

【CJWYH】RHL的背包题解(多重背包)

题面 [问题描述] CJ中学组织学生出去春游,作为学神的RHL自然不会放过这一大好时机,他有n种物品,第i件物品有c[i]个,每个体积为v[i],价值为w[i],RHL现在有一个体积为V的背包,他想让他带的东西价值之和最大,且体积之和不超过V,你能帮帮他吗?注意物体不能分割. [输入] 输入文件名为bag.in,分为若干行.第一行包含两个正整数n,V. 第二行到第n+1行分别描述第i种物品的数量c[i],体积v[i],价值w[i] [输出] 输出文件名为bag.out,一行输出一个整数,表示最大

01背包模板、全然背包 and 多重背包(模板)

转载请注明出处:http://blog.csdn.net/u012860063 贴一个自觉得解说不错的链接:http://www.cppblog.com/tanky-woo/archive/2010/07/31/121803.html 模版就直接贴代码: 01背包模板: /* 01背包问题 01背包问题的特点是,">每种物品仅有一件.能够选择放或不放. 01背包问题描写叙述: 有N件物品和一个容量为V的背包. 第i件物品的重量是c[i],价值是w[i]. 求解将哪些物品装入背包可使这些物品

hdu2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 (这个只是题目名字) (多重背包)

本文出自:http://blog.csdn.net/svitter 原题:http://acm.hdu.edu.cn/showproblem.php?pid=2191 题意:多重背包问题.转换成为01背包解.多重背包转化为01背包的关键在于把件数从整体中孤立出来作为一个新的个体,也就是说不管分类,有多少件就有多少种. AC代码: //============================================================================ // Na

【POJ1882】Stamps,灵活多重背包,详细题意!!!(题解也有)

我之所以发题解(题意),就是因为百度搜索上发的太少了,而且还不清晰,所以: 题意:我直接拿数据说话吧(可以直接看下面的大号粗体字,如果你语文够好的话.) 5 2 4 1 4 12 21 4 1 5 12 28 10 2 5 1 7 16 31 88 5 1 15 52 67 99 6 2 3 1 5 8 4 1 5 7 8 0 第一行 5 是最多能拿5张邮票,第二行2是有两组邮票. 第三行4是该组有4张邮票,然后4个数是4个面额. 第五行"10"开始就是下一组数据了,输入到"

DZY Loves Math II:多重背包dp+组合数

Description Input 第一行,两个正整数 S 和 q,q 表示询问数量.接下来 q 行,每行一个正整数 n. Output 输出共 q 行,分别为每个询问的答案. Sample Input 30 3 9 29 1000000000000000000 Sample Output 0 9 450000036 Hint 感谢the Loser协助更正数据对于100%的数据,2<=S<=2e6??,1<=n<=101810^{18}10?18??,1<=q<=10

【动态规划】背包问题(一) 01背包 完全背包 多重背包

一.01背包 有N件物品和一个容量为V的背包.第i件物品的价格(即体积,下同)是w[i],价值是c[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 这是最基础的背包问题,总的来说就是:选还是不选,这是个问题<( ̄ˇ ̄)/ 相当于用f[i][j]表示前i个背包装入容量为v的背包中所可以获得的最大价值. 对于一个物品,只有两种情况 情况一: 第i件不放进去,这时所得价值为:f[i-1][v] 情况二: 第i件放进去,这时所得价值为:f[i-1][v-c[i]]+w