背包的。

首先是自由评述:这几天的背包问题

0 1包:逆序。结果由上一组元素刷过去的结果得来的。

 1 void ZeroOnePack(int val,int vol)
 2 {
 3
 4     int i;
 5     for(i=V;i>=vol;i--)
 6     {
 7         if(dp[i-vol]+val>dp[i])
 8         {
 9             dp[i] = dp[i-vol]+val;
10         }
11     }
12 }

01背包

满 包:初始化的时候。这个有个好方法 -inf 其中const int inf = 1<<28-1;这样的。写在顶部

    结果符合的得重新附值。 dp[0]=0常见的。

    原理:明确的是这个值要足够小或者大。能导致过滤掉这个结果。

       可以用这个来做 至多和至少问题。已经必须放入多少个的问题。

       我想法是弄成二维的 然后至少往上搜。至多往下搜。已经必须放入多少的直接在这一层搜索。

完全背包:顺序。注意这个复杂度只有N*V了。因为不是一个物品刷一层循环 而是一种物品刷一层循环。并不能用01包的原理去单纯解释。

 1 void ZeroOnePack(int val,int vol)
 2 {
 3
 4     int i;
 5     for(i=vol;i<=V;i+)
 6     {
 7         if(dp[i-vol]+val>dp[i])
 8         {
 9             dp[i] = dp[i-vol]+val;
10         }
11     }
12 }

完全背包

多重背包:如果说是利用完全包的刷一层方法。并不好知道你的个数使用了多少来维护个数!。所以分完全包的情况vol*num>=V 也就是说在这个范围内你     可以随意数量放置。(当然拉。必须是最优的。)而如果小于这个值 就用01包。 但是是用bin优化过的再进行01包。 这个时候是顺序还是逆序     呢?是顺序的。理解可以用01包去里面。当初错误理解完全包的方法可以在这里得到好的解释。所以用一个变量k=1 来进行。最后还得进行一次     num的01至于为什么 这个和bin 有关

 1 void MulPack(int val,int vol,int num)
 2 {
 3     if(val*num>=aver)
 4     {
 5         ComPack(val,vol);
 6         return;
 7     }
 8
 9     int k=1;
10     while(k<num)
11     {
12         ZeroOnePack(k*val,k*vol);
13
14         num -= k;
15         k *= 2;
16     }
17     ZeroOnePack(num*val,num*vol);
18 }

多重背包

混合背包:这种背包并不难,只要传入方式正确。以及注意满包问题。

 1 int max(int a,int b)
 2 {
 3     return a>b?a:b;
 4 }
 5 void OneZeroPack(int val,int vol)
 6 {
 7     int j;
 8     for(j=V;j>=vol;j--)
 9     {
10         dp[j] = max(dp[j],dp[j-vol]+val);
11     }
12 }
13 void ComPack(int val,int vol)
14 {
15     int j;
16     for(j=vol;j<=V;j++)
17     {
18         dp[j] = max(dp[j],dp[j-vol]+val);
19     }
20 }
21 void MulPack(int val,int vol,int num)
22 {
23     if(val*num>=V)
24     {
25         ComPack(val,vol);
26         return;
27     }
28     int k = 1;
29     while(k<num)
30     {
31         OneZeroPack(val,vol);
32         num -= k;
33         k *= 2;
34     }
35     OneZeroPack(val,vol);
36 }

上述三种在一起。

二维费用:说白了是添加一个数组。多一层循环。实际上经常和满包之类的在一起。这个时候注意初始化即可。另外,二维费用经常出现的是数目的限制。

     必须放入指定M个数目。这个时候往往就是满包问题了。状态划分也得注意其含义的变化了。其实如果没有这类问题。那个数目限制还有什么意     义啊!。也对。其实我们是为了满足条件才使用的二维。然后状态方程使用来源法即可。

时间: 2024-08-05 07:15:07

背包的。的相关文章

HDU 2189 悼念512汶川大地震遇难同胞——来生一起走(母函数或完全背包)

悼念512汶川大地震遇难同胞--来生一起走 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3773    Accepted Submission(s): 1913 Problem Description 妈妈你别哭泪光照亮不了我们的路让我们自己慢慢的走 妈妈我会记住你和爸爸的模样记住我们的约定来生一起走 上面这首诗节选自一位诗人纪念遇难

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

17-又见01背包

/*                                        又见01背包时间限制:1000 ms  |  内存限制:65535 KB难度:3 描述        有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W     的物品,求所有挑选方案中物品价值总和的最大值.    1 <= n <=100    1 <= wi <= 10^7    1 <= vi <= 100    1 <= W <= 10^

Leetcode 494 Target Sum 动态规划 背包+滚动数据

这是一道水题,作为没有货的水货楼主如是说. 题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20))和一个数S c1a1c2a2c3a3......cnan = S, 其中ci(1<=i<=n)可以在加号和减号之中任选. 求有多少种{c1,c2,c3,...,cn}的排列能使上述等式成立. 例如: 输入:nums is [1, 1, 1, 1, 1], S is 3. 输出 : 5符合要求5种

HDU - 2602 Bone Collector(01背包讲解)

题意:01背包:有N件物品和一个容量为V的背包.每种物品均只有一件.第i件物品的费用是volume[i],价值是value[i],求解将哪些物品装入背包可使价值总和最大. 分析: 1.构造二维数组:dp[i][j]---前i件物品放入一个容量为j的背包可以获得的最大价值. dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - volume[i]] + value[i]);---(a) (1)dp[i - 1][j]---不放第i件物品,因此前i件物品放入一个容量为

UVa 12563 劲歌金曲(0-1背包)

https://cn.vjudge.net/problem/UVA-12563 题意:求在给定时间内,最多能唱多少歌曲,在最多歌曲的情况下,使唱的时间最长. 思路:很明显背包容量为t-1,因为至少得留下1秒钟来放<劲歌金曲>.题目要求的首先唱的歌要多,其次才是要时间长. 这里需要用到一个技巧:对决策进行一定的限定!在计算某个时间最多唱的歌曲时,必须是该时间内恰好唱完这些歌,时间多了不行. 所以在下面的代码中,首先将d数组都声明为了-1,如果不是在该时间内正好唱完歌,那么d[j - a[i]]

(背包dp)UVA - 562 Dividing coins

题意:有n个硬币,每个硬币有个价值,两个人分配硬币,要求最公平分配时候两人拿到的钱的差. 分析:很明显,两人拿到的钱的差越小越公平. 一开始想,一定是一人一半最公平,所以直接把总和sum/2,对着half跑01背包,但是WA了,修改后分别讨论奇偶,额外进行一次sum-half的01背包,也WA,仔细想想觉得有些漏洞. 所以,这题其实可以干脆直接跑sum的背包,不断更新ans=min(ans,sum-dp[j]*2)就行了.如果ans==inf,表示不能分,也就是1个,这时输出0. 代码: 1 #

01背包

这里就只放自己刷的题目了,毕竟是弱弱哒 HDU2546:饭卡 1 #include <algorithm> 2 #include <cstdio> 3 4 using namespace std; 5 6 int main() 7 { 8 int n,m; 9 while (~scanf("%d", &n), n) 10 { 11 int f[2013] = {0}, menu[2013] = {0}; 12 for (int i = 1; i <

[hdu5445 Food Problem]多重背包

题意:一堆食物,有价值.空间.数量三种属性,一些卡车,有空间,价格,数量三种属性.求最少的钱(不超过50000)买卡车装下价值大于等于给定价值的食物,食物可以拆开来放. 思路:这题的关键是给定的条件:食物可以拆开来放.这个条件使得卡车和食物可以分开考虑,然后通过空间这个属性联系在一起.做两遍多重背包即可. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

HDU 1011 Starship Troopers(树形dp+背包)

Starship Troopers Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13109    Accepted Submission(s): 3562 Problem Description You, the leader of Starship Troopers, are sent to destroy a base of