01背包问题--动态规划解法

从01背包问题理解动态规划

  01背包问题具体例子:假设现有容量10kg的背包,另外有3个物品,分别为a1,a2,a3。物品a1重量为3kg,价值为4;物品a2重量为4kg,价值为5;物品a3重量为5kg,价值为6。将哪些物品放入背包可使得背包中的总价值最大?

  这个问题有两种解法,动态规划和贪婪算法。本文仅涉及动态规划。

  先不套用动态规划的具体定义,试着想,碰见这种题目,怎么解决?

  首先想到的,一般是穷举法,一个一个地试,对于数目小的例子适用,如果容量增大,物品增多,这种方法就无用武之地了。

  其次,可以先把价值最大的物体放入,这已经是贪婪算法的雏形了。如果不添加某些特定条件,结果未必可行。

  最后,就是动态规划的思路了。先将原始问题一般化,欲求背包能够获得的总价值,即欲求前i个物体放入容量为m(kg)背包的最大价值c[i][m]——使用一个数组来存储最大价值,当m取10,i取3时,即原始问题了。而前i个物体放入容量为m(kg)的背包,又可以转化成前(i-1)个物体放入背包的问题。下面使用数学表达式描述它们两者之间的具体关系。

  表达式中各个符号的具体含义。

  w[i] :  第i个物体的重量;

  p[i] : 第i个物体的价值;

  c[i][m] : 前i个物体放入容量为m的背包的最大价值;

  c[i-1][m] : 前i-1个物体放入容量为m的背包的最大价值;

  c[i-1][m-w[i]] : 前i-1个物体放入容量为m-w[i]的背包的最大价值;

  由此可得:

      c[i][m]=max{c[i-1][m-w[i]]+pi , c[i-1][m]}(下图将给出更具体的解释)

    根据上式,对物体个数及背包重量进行递推,列出一个表格(见下表),表格来自(http://blog.csdn.net/fg2006/article/details/6766384?reload) ,当逐步推出表中每个值的大小,那个最大价值就求出来了。推导过程中,注意一点,最好逐行而非逐列开始推导,先从编号为1的那一行,推出所有c[1][m]的值,再推编号为2的那行c[2][m]的大小。这样便于理解。

    

动态规划【正解】

有N件物品和一个容量为V的背包。第i件物品的体积是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
状态转移方程:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]} 
这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的 
伪码:
  for i=1..N 
   for v=V..0 
    f[v]=max{f[v],f[v-c[i]]+w[i]};
如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,
价值为f[i-1][v];
如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,
此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。

②例题二:
采药

Time Limit:   1000MS       Memory Limit:   65535KB 
Submissions:   155       Accepted:   50

Description辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?  
Input输入的第一行有两个整数T(1 <= T <= 1000)和M(1 <= M <= 100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。 
Output输出包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。 
Sample Input
70 3
71 100
69 1
1 2
Sample Output
3

#include<iostream>
# include<cstring>
# define max(a,b) a>b?a:b
using namespace std;
int main()
{

    int dp[101][1001],m,T,w[101],val[101],i,j;
    cin>>T>>m;
    for(i=1;i<=m;i++)
        cin>>w[i]>>val[i];
    memset(dp,0,sizeof(dp));
    for(i=1;i<=m;i++)
     for(j=0;j<=T;j++)//j相当于上面说的V-c[i]
         {
    if(j>=w[i])
        dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+val[i]);//放还是不放的选择
    else dp[i][j]=dp[i-1][j];
     }
     cout<<dp[m][T]<<endl;
     return 0;
} 

时间: 2024-08-24 10:04:38

01背包问题--动态规划解法的相关文章

01背包问题--动态规划解法(2)(转载)

本章主要讲述最简单的背包问题,从如何建立状态方程到如何根据状态方程来实现代码,再到如何优化数据结构,让我们对动态规划的建立与求解认识更加透彻 题目: 有N件物品和一个容量为V的背包.放入第i件物品的费用是Ci,得到的价值是Wi.求解将哪些物品装入背包可使价值和最大. 分析: (一)建立状态方程 这是最基础的背包问题,直接说状态转移方程了,设dp[i][v]表示前i件物品放入容量为v的背包能获得的最大价值,每件物品可以选择放与不放,则有: dp[i][v]=max{dp[i-1][v],dp[i-

《算法导论》读书笔记之第16章 0-1背包问题—动态规划求解

原文:http://www.cnblogs.com/Anker/archive/2013/05/04/3059070.html 1.前言 前段时间忙着搞毕业论文,看书效率不高,导致博客一个多月没有更新了.前段时间真是有些堕落啊,混日子的感觉,很少不爽.今天开始继续看算法导论.今天继续学习动态规划和贪心算法.首先简单的介绍一下动态规划与贪心算法的各自特点及其区别.然后针对0-1背包问题进行讨论.最后给出一个简单的测试例子,联系动态规划实现0-1背包问题. 2.动态规划与贪心算法 关于动态规划的总结

01背包问题-动态规划算法

转 https://www.cnblogs.com/Christal-R/p/Dynamic_programming.html 一.问题描述:有n 个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和? 二.总体思路:根据动态规划解题步骤(问题抽象化.建立模型.寻找约束条件.判断是否满足最优性原理.找大问题与小问题的递推关系式.填表.寻找解组成)找出01背包问题的最优解以及解组成,然后编写代码实现: 三.动态规划的原理及过程: eg:number=4,ca

0-1背包问题——动态规划

1 // 动态规划法解决0-1背包问题 2 //example: 3 //物品种类n=5,背包容量c=10, 4 //物品的重量向量 w={2,2,6,5,4},物品的价值向量 v={6,3,5,4,6} 5 // O(min{n*c,2^n}) 6 #include "stdafx.h" 7 #include <cstdlib> 8 #include <iostream> 9 10 using namespace std; 11 template<cla

0-1背包问题与分数背包问题

0-1背包问题与分数背包问题 问题描述 问题分析之分数背包 代码设计之分数背包问题 问题分析之0-1背包问题 代码设计之0-1背包问题 动态规划算法之间的差别 0-1背包问题与分数背包问题 我们在文章<贪心算法原理>:http://blog.csdn.net/ii1245712564/article/details/45369491中提到过动态规划和贪心算法的区别.以及两个经典的例子:0-1背包问题和分数背包问题,我么知道0-1背包问题是不能够使用贪心算法求解的,而贪心算法则是分数背包问题的不

背包问题基本解法 —— 《背包九讲》笔记

相对于转载文章,我更喜欢写上一篇笔记,开篇给出原文链接.这样,能有些自己的东西,总结一番,对知识的理解能加深一层:别人看来,也更有价值. 今天做USACO题目时,一道题不会,网上查到解法是01背包,于是重新看了<背包九讲>.相比第一次看,理解深的多,可见我还是在进步的,只要我没停下脚步.如果大家想看原文,那么只需要百度“背包九讲”就好了,百度文库中的“背包九讲 2.0”是正版,作者是崔添翼前辈,网上好像称他为dd大牛.这篇文章可以说是“背包问题”的权威了,如果我了解无误的话,背包问题的整套解法

ACM1881 01背包问题应用

01背包问题动态规划应用 acm1881毕业bg 将必须离开的时间限制看作背包容量,先将他们由小到大排序,然后在排完序的数组中对每个实例都从它的时间限制开始(背包容量)到它的延长时间进行遍历: 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 struct BG 6 { 7 int h,t,l; 8 friend bool operator<

【动态规划】01背包问题_两种解法

问题描述 0-1背包问题:给定\(n\)种物品和一背包.物品i的重量是\(w_i\),其价值为\(v_i\),背包的容量为\(C\).问:应该如何选择装入背包的物品,使得装人背包中物品的总价值最大? 在选择装人背包的物品时,对每种物品\(i\)只有两种选择,即装人背包或不装入背包.不能将物品\(i\)装入背包多次,也不能只装入部分的物品\(i\).因此,该问题称为0-1背包问题. 此问题的形式化描述是,给定\(C>0\),\(w_i>0\),\(v_i>0\),\(1≤i≤n\),要求找

01背包问题的动态规划算法

01背包问题我最初学会的解法是回溯法,第一反应并不是用动态规划算法去解答.原因是学习动态规划算法的时候,矩阵连乘.最长公共子串等问题很容易将问题离散化成规模不同的子问题,比较好理解,而对于01背包问题则不容易想到将背包容量离散化抽象出子问题,从情感上先入为主也误以为动态规划算法不是解决01背包问题的好方法,实际上并不是这样的.另外,动态规划算法不对子问题进行重复计算,但是要自底向上将所有子问题都计算一遍,直到计算出最终问题的结果也就是我们要的答案,有点像爬山的感觉. 问题描述:给定n种物品和一背