又鸽了好久……

前言

博主刚刚学会背包问题不久,然后有一段时间没练习了

今天就来重新温习一下,顺手就写了这一篇博客。

好了,下面进入正题!

算法简介

背包问题是动态规划的一个分支

主要是分成了01背包、完全背包和多重背包。

下面从01背包开始讲解。

背包算法介绍

01背包

基本概念

01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2至Wn,与之相对应的价值为P1,P2至Pn。01背包可谓是背包问题中最简单的问题。01背包的约束条件是给定几种物品,每种物品有且只有一个,并且有权值和体积两个属性。在01背包问题中,因为每种物品只有一个,对于每个物品只需要考虑选与不选两种情况。如果不选择将其放入背包中,则不需要处理。如果选择将其放入背包中,由于不清楚之前放入的物品占据了多大的空间,需要枚举将这个物品放入背包后可能占据背包空间的所有情况。

问题雏形

有N件物品和一个容量为V的背包。第i件物品的体积是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

问题解答

了解了基本概念和问题雏形后我们就可以来想做题的方法了。

从题目里看,我们就能看出,01背包有个特点:每种物品仅有一件,可以选择放或不放。

所以我们就可以把每种情况都枚举一遍。

首先建立一个二维数组dp[][]表示价值,w[i]是每件物品的价值,c[i]是每件物品的体积

然后就想,由于它只有放和不放两种状态,我们就要比较这两种状态的价值,用max函数。

状态转移方程:dp[i][v]=max{dp[i-1][v],dp[i-1][v-c[i]]+w[i]}

其中,dp[i-1][v]表示不放该物品,dp[i-1][v-c[i]]+w[i]表示放入该物品。

这样做一个循环枚举各种情况即可。

for (i = ; i <= n; i++)
for (j = v; j >= c[i]; j--)//在这里,背包放入物品后,容量不断的减少,直到再也放不进了
dp[i][j] = max(dp[i - ][j], dp[i - ][j - c[i]] + w[i]);

最后的结果就是最大值。

还有一些优化的方法:01滚动就地滚动

01滚动:

我们可以看到每一行的结果实际上只与上一行有关,所以就可以01滚动——f[i][0,1] 一行记录前一行的值,另一行记录当前行的值……

所以,这是一种简化的好办法!

就地滚动:

就地滚动就是用一个一维数组,把之前的状态和当前的状态放在同一个数组,但是在写的过程中会有问题。

先上代码吧:

for(i= ; i<= n ; i++)
for(j= c[i]; j<v ; j++)     
if(!dp[j-c[i]) dp[j] = dp[j-c[i]];

我们会发现,这样的话一个物品会被重复计算多次。

实战演练

问题1:采药

这是一个经典的问题哦!

飞机场:洛谷P1048 采药

问题解答(不可用于直接AC本题,可进行参考!)

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define inf 100000000
//状态:dp[i][j]表示考虑前i个草药,目前体积之和为j,可以获得的最大价值
//转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])
//答案:dp[m][max(...)]
//不需要初始化,直接算
//复杂度:O(m*t)
int dp[][],w[],v[];
using namespace std;
int main()
{
int t,m;
cin>>t>>m;
for(int i=;i<=m;i++)
{
cin>>w[i]>>v[i];
}
for(int i=;i<=m;i++)
for(int j=t;j>=;j--)
{
if(j-w[i]>=)
dp[i][j]=max(dp[i-][j],dp[i-][j-w[i]]+v[i]);
else
dp[i][j]=dp[i-][j];
}
int ans=;
for(int i=;i<=t;i++)
{
ans=max(dp[m][i],dp[m][i-]);
}
cout<<ans;
return ;
}

当然还有一种做法。可以直接使用一维数组:参见一本通。

完全背包

基本概念

这个问题非常类似于01背包问题,所不同的是每种物品有无限件,也就是从每种物品的角度考虑,与它相关的策略已并非取或不取两种,而是有取0件、取1件、取2件……取[V/c]件等很多种。

问题雏形

有 N 种物品和一个容量为 V 的背包,每种物品都有无限件可用。放入第 i 种物品的费用是 Ci ,价值是 Wi 。求解:将哪些物品装入背包,可使这些物品的耗费的费用总和不超过背包容量,且价值总和最大。

问题解答

这个题目有一个和01背包不一样的地方:每种物品有无数件!

然后我们想前面我说过的就地滚动,会计算多次,这不正巧?

实战演练

问题2:疯狂的采药

这个……这个题目的介绍不大正经,未成年人请在家长的陪伴下观看。

飞机场:洛谷P1616 疯狂的采药

问题解答(不可用于直接AC本题,可进行参考!)

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define inf 100000000
//状态:dp[i][j]表示考虑前i个草药,目前体积之和为j,可以获得的最大价值
//转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])
//答案:dp[m][max(...)]
//不需要初始化,直接算
//复杂度:O(m*t)
int f[],t,m,ti,v;
using namespace std;
int main()
{
cin>>t>>m;
for(int i=;i<=m;i++)
{
cin>>ti>>v;
for(int j=ti;j<=t;j++)
f[j]=max(f[j],f[j-ti]+v);
}
cout<<f[t];
return ;
}

多重背包

基本概念&问题雏形

有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件体积是w[i],价值是v[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

问题解答

这个问题的特点是:每种物品有一定数量

这个运用的是二进制思想

转化为01背包求解:把第i种物品换成n[i]件01背包中的物品,则得到了物品数为Σn[i]的01背包问题。

我们考虑把第i种物品换成若干件物品,使得原问题中第i种物品可取的每种策略——取0..n[i]件——均能等价于取若干件代换以后的物品。

另外,取超过n[i]件的策略必不能出现。 方法是:将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。

使这些系数分别为1,2,4,...,2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。

解决问题的道理

1) 1+2+4+...+2^(k-1)+n[i]-2^k+1 = n[i]   这就保证了最多为n[i]个物品

2)1,2,4,……,2^(k-1),可以凑出1到2^k – 1的所有整数(联系一个数的二进制拆分即可证明,证明过程在下面的题解中)

3) 2^k……n[i]的所有整数可以用若干个上述元素凑出(可以理解为凑n[i]-t, 而n[i]为上面所有数的和,t则是一个小于2^k 的数,那么在所有的数中去掉组成2^k 的那些数剩下的就可以组成n[i]-t了)

当然,这个二进制的道理我在之前的一篇博客上写过,一会的实战演练会带你们去。

实战演练

问题3:宝物筛选

这是一道很水的蓝题……

飞机场:洛谷P1776 宝物筛选题解(我写的,你们还有更详细的多重背包解决思路)


后记

本文就写这么多了,背包问题在考试中会经常出现,希望大家深入理解其中的思想。

客官,给个赞再走呗?

c++背包问题的更多相关文章

  1. DSY3163*Eden的新背包问题

    Description "寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听."失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的 ...

  2. 使用adagio包解决背包问题

    背包问题(Knapsack problem) 背包问题(Knapsack problem)是一种组合优化的多项式复杂程度的非确定性问题(NP问题).问题可以描述为:给定一组物品,每种物品都有自己的重量 ...

  3. bzoj 3163: [Heoi2013]Eden的新背包问题

    Description "寄没有地址的信,这样的情绪有种距离,你放着谁的歌曲,是怎样的心心静,能不能说给我听."失忆的Eden总想努力地回忆起过去,然而总是只能清晰地记得那种思念的 ...

  4. nyoj 106背包问题(贪心专题)

    背包问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w< ...

  5. [C++11][算法][穷举]输出背包问题的所有可满足解

    关于背包问题的题目,前人之述备矣,这里只讨论实现 输入: n ca w_1 v_1 w_2 v_2 ... w_n v_n 其中,n是物品总数,ca是背包大小,w_n是第n个物品的重量,v_n是第n个 ...

  6. knapsack problem 背包问题 贪婪算法GA

    knapsack problem 背包问题贪婪算法GA 给点n个物品,第j个物品的重量,价值,背包的容量为.应选哪些物品放入包内使物品总价值最大? 规划模型 max s.t. 贪婪算法(GA) 1.按 ...

  7. NOIP2006金明的预算方案[DP 有依赖的背包问题]

    题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”.今 ...

  8. bzoj2748[HAOI2012]音量调节(背包问题的方案)

    Description 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都要改变一次音量.在演出开始之前,他已经做好了一个列表,里面写着在每首歌开始之前他想要改 ...

  9. 【动态规划】简单背包问题II

    问题 B: [动态规划]简单背包问题II 时间限制: 1 Sec  内存限制: 64 MB提交: 21  解决: 14[提交][状态][讨论版] 题目描述 张琪曼:“为什么背包一定要完全装满呢?尽可能 ...

  10. ACM 背包问题

    背包问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w< ...

随机推荐

  1. 14 微服务电商【黑马乐优商城】:day03-springcloud(Hystix,Feign)

    本项目的笔记和资料的Download,请点击这一句话自行获取. day01-springboot(理论篇) :day01-springboot(实践篇) day02-springcloud(理论篇一) ...

  2. Java之关键字abstract(抽象类与抽象方法)

    /* * abstract关键字的使用 * 1.abstract:抽象的 * 2.abstract可以用来修饰的结构:类.方法 * * 3. abstract修饰类:抽象类 * > 此类不能实例 ...

  3. 实战_4:UI开发工具-WindowBuilder

    介绍: WindowBuilder是谷歌开发的,开发java图形界面的工具,是一个eclipse插件. WindowBuilder支持开发多种形式的图形界面:SWT/JFace.Swing.GWT 安 ...

  4. unittest如何在循环遍历一条用例时生成多个测试结果

    引用自:http://blog.csdn.net/kaku21/article/details/42124593 参考网址:http://programmaticallyspeaking.com/te ...

  5. 【flask】RestFul的基本鉴权

    编写API的基本鉴权 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Author : shenqiang from flask import Fla ...

  6. Xen入门系列三【Xen 管理工具 xm】

    xm命令是管理Xen的最基本的工具,可以通过xm --help 来获得帮助. 1. 列出所有正在运行的虚拟操作系统 # xm list PS[1]:可缩写为 xm li 2. 启动虚拟机 # 通过配置 ...

  7. [Linux] Ubuntu 配置nfs

    安装NFS Server: 1. 执行命令 "$ sudo apt-get install nfs-kernel-server",安装nfs server 端 2. 创建需要用来分 ...

  8. sql server 数据库连接方式分析、详解

    本文链接:https://blog.csdn.net/wang379275614/article/details/7859398 一.OLEDB方式连接Sql身份验证模式:Provider=" ...

  9. 用Spring Tool Suite简化你的开发

    如果你是一个喜欢用spring的人,你可能会在欣赏spring的强大功能外,对其各样的配置比较郁闷,尤其是相差较大的版本在配置文件方面会存在差异,当然你可以去花不少的时间去网上查找相关的资料,当你准备 ...

  10. OSI体系结构(七层)

    OSI体系结构,意为开放式系统互联.国际标准组织(国际标准化组织)制定了OSI模型.这个模型把网络通信的工作分为7层,分别是物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 1至4层被认为 ...