背包问题整理;

一、01背包;

1.背景:N件物品,和一个容量为V的背包,每件物品体积为C[i],价值为W[i],求在总体积不超过V的情况下,每件物品可以放或不放,获得的最大价值;

2.分析:我们把问题分成一个小问题,设f[i][v]代表在前i件物品中选择,并且获得容量为v的情况下,所获得最大价值;

则动态转移方程为f[i][v]=max(f[i-1][v],f[i-1][v-c[i]]+w[i]);

3.上述方法时间复杂度为O(V*N),空间复杂度为O(V*N);

优化空间复杂度,可以看到我们的最终答案只在f[n][v]中,因此,我们可以将f[i][v]化简为f[v];

则方程为:

for (i=1;i<=n;i++)

for (j=v;j>=c[i];j--)

f[j]=max(f[j],f[j-c[i]]+w[i]);

其中第一层循环选择物品,第二次选择容积是否满足最大价值条件,其中v应该从大到小,否则每一件物品会被选择多次;

二、完全背包;

1.背景相同,每件物品可以被选择多次;

2.分析:同样设f[i][v]代表在前i件物品中选择,并且获得容量为v的情况下,所获得最大价值;

动态方程为:f[i][v]=max(f[i][v],f[i-1][v-k*c[i]]+k*w[i]),其中代表第i件物品选择k次;

3.优化时间和空间复杂度,首先先看优化前的代码;

for(i=1;i<=n;i++)

for (k=0;k*c[i]<=v;k++)

for (j=v;j>=k*c[i];j--)

f[i][j]=max(f[i][j],f[i-1][j-k*c[i]]+k*w[i]);

我们可以说f[i][j]=f[i-1][j-c[i]]+w[i]=f[i-1][j-2*v[i]]+w[i]*2=.....=f[i-1][j-k*c[i]]+k*w[i];

从后面向前推的话,假设k为v容积可以取到最多的i物品个数,假设我们已经将f[i-1][j-k*v[i]]求出来了;

则前面的我们可以直接递推过来,

如for(j=c[i];j<=V;j++)

f[i][j]=max(f[i][j],f[i][j-c[i]]+w[i]);

其中我们可以看到每一个f[i][j-c[i]]都为最优值;故我们可以把每件物品取无限次,省去k这重循环;

依照第一类问题我们再优化空间复杂度,可得;

for(i=1;i<=n;i++)

for (j=c[i];j<=v;j++)

f[j]=max(f[j],f[j-c[i]]+w[i]);

三、多重背包

1、背景:同上,不同每种物品有n[i]件;

2.分析:不难想到,我们可以用完全背包未化简之前的公式,f[i][j]=max(f[i][j],f[i-1][j-k*c[i]]+k*w[i]);

其中k小于n[i];

3.优化

我们可以将n[i]看做二进制数,则2^k代表第k+1位所代表的数,则小于n[i]的数都可以表示出来,其中n[i]>=2^(k+1);最后一个数字直接由n[i]-所有值的和;

比如

for(i=1;i<=N;i++)

{

int sum=0;

for (k=0;2^(k+1)<=n[i];k++)

{

for (j=v;j>=2^(k)*c[i];j--){

f[j]=max(f[j],f[j-2^(k)*c[i]]+w[i]*2^(k));

sum+=2^(k);

}

sum=n[i]-sum;

for (j=v;j>=sum*c[i];j--)

f[j]=max(f[j],f[j-sum*c[i]]+w[i]*sum);

}

四、混合背包

1.上述各种背包的组合;

2.分析:

时间: 2024-10-25 11:24:58

背包问题整理;的相关文章

背包问题整理

背包问题 给定一组物品,每种物品都有自己的重量和价值,现有一个背包,能承受的重量有限,在受限制的重量下,取若干物品,使得总价值最大.这一类问题,被称为背包问题. 01背包(物品个数为1) for (int i = 1; i <= N; ++i) { for (int j = 0; j <= V; ++j) { if(j >= c[i]) { dp[i][j] = max(dp[i - 1][j - c[i]] + w[i], dp[i - 1][j]); } else { dp[i][j

背包问题【01、完全(恰好or不超过)、多重】【尚未整理完】

要点: (仨黄色背景代码为三个问题最终用的模板) 1.一维的01背包为啥要逆序(保证更新f[j]时,f[ j - weight[i] ]是没有放入物品i时的数据即f[ i - 1 ][ j - weight[i] ],因为01背包每个物品至多被选一次.而完全背包中,每个物品可以被选无限次,那么状态f[i][j],正好可以由可能已经放入物品i的状态f[ i - 1 ][ j - weight[i] ]转移而来.所以,遍历顺序改为顺序时,就是完全背包问题,其余都不用变~) 2.完全背包 和 01背包

背包问题简单整理

hdu2546,01背包,需要有点变形,计算时需要把价格最大的菜先放一边,最后计算. #include<iostream> #include<cstdio> #include<set> #include<map> #include<vector> #include<iterator> #include<algorithm> #include<cstring> using namespace std; int V

夏令营讲课内容整理 Day 5.

DP专场.. 动态规划是运筹学的一个分支, 求解决策过程最优化的数学方法. 我们一般把动态规划简称为DP(Dynamic Programming) 1.动态规划的背包问题 有一个容量为m的背包,有n个物品,每一个物品i的重量为w[i],价值为v[i]. 要求选择一些物品放入背包中,每种物品只能最多使用一次,使得在不超重的情况下让背包中所有物品价值总和最大. 正常向解法:设状态数组f[i][j]为把前i个物品放入一个容量为j的背包中所能获得的最大价值(以下同设),则状态转移方程为: f[i][j]

DP——背包问题(一)

以前不是很重视 DP ,遇到 DP 就写贪心.暴搜--其实这是非常错误的,现在开始练习 DP 了才发现,我好菜-- 对于DP的整理,先从众所周知的背包问题开始. -------- 01背包:n 个物品,重量和价值分别为 w[i].v[i],背包容量 W,求所有挑选方案中价值总和的最大值. DP 方程 :dp[j] = max ( dp[j] , dp[ j - w[i] ] + v[i] ) ,其中 dp[j]为使用 j 的容量获得的最大价值,i 为第 i 件物品. 代码: 1 #include

【转】国家集训队论文分类整理 作者:洪雁书

距离NOI时间越来越少了,选择性地看一些集训队论文是很有必要的. (在此给已经看过所有论文的神牛跪了= =) 所以,我在此整理了一下,供大家参考. 组合数学 计数与统计 2001 - 符文杰:<Pólya原理及其应用> 2003 - 许智磊:<浅谈补集转化思想在统计问题中的应用> 2007 - 周冬:<生成树的计数及其应用> 2008 - 陈瑜希<Pólya计数法的应用> 数位问题 2009 - 高逸涵<数位计数问题解法研究> 2009 - 刘聪

我自己的Android面试试题总结整理

http://blog.sina.com.cn/s/blog_ad991b1601018mjc.html 2013-5-9号补充:今天最新的腾讯面试题,应该说是所有面试中最难的,我个人感觉.而且是个女面试官,好嗨皮啊,哈哈. 腾讯面试题 1.int a = 1; int result = a+++3<<2; 2.int a = 2; int result = (a++ > 2)?(++a):(a+=3); 3.int a = 1234567; int b = 0x06; int resu

【转】牛人整理分享的面试知识:操作系统、计算机网络、设计模式、Linux编程,数据结构总结

基础篇:操作系统.计算机网络.设计模式 一:操作系统 1. 进程的有哪几种状态,状态转换图,及导致转换的事件. 2. 进程与线程的区别. 3. 进程通信的几种方式. 4. 线程同步几种方式.(一定要会写生产者.消费者问题,完全消化理解) 5. 线程的实现方式. (也就是用户线程与内核线程的区别) 6. 用户态和核心态的区别. 7. 用户栈和内核栈的区别. 8. 内存池.进程池.线程池.(c++程序员必须掌握) 9. 死锁的概念,导致死锁的原因. 10. 导致死锁的四个必要条件. 11. 处理死锁

0-1背包问题与子集合加总问题的近似算法

最近没有怎么更新博客,因为一直比较忙.最近发现所里在做的一个项目中,可以抽出一部分内容和0-1背包问题.子集合加总问题非常相似(虽然表面上不容易看出相似点),所以看了一些这方面的资料和论文,这里主要对问题特点和算法思想做一些整理.这类问题其实很有意思,做数学和做计算机的人都会研究,而且我这里将要提到的论文都是做计算机的人所写的. 问题简述0-1 Knapsack Problem (0-1背包问题,下面简称KP)和Subset Sum Problem (子集合加总问题,下面简称SSP)是经典的NP