动态规划之背包问题 python实现

来源:互联网 发布:js dialog 关闭事件 编辑:程序博客网 时间:2024/06/13 04:23

动态规划之01背包问题

题目描述:有编号分别为1,2,3,4,5的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?
动态规划的核心过程有两部分,一个是找出问题的”子状态”,再一个就是建立“状态转移方程”(所谓的递推公式)。将上面的问题解决,动态规划就解了一般,剩下的为代码将数学的公式的进行实现。
- 动态规划的思路。先将原始问题一般化,欲求背包能够获得的总价值,即欲求前i个物体放入容量为m(kg)背包的最大价值c[i][m]——使用一个数组来存储最大价值,当m取10,i取3时,即原始问题了。而前i个物体放入容量为m(kg)的背包,又可以转化成前(i-1)个物体放入背包的问题。下面使用数学表达式描述它们两者之间的具体关系。
- w[i]:第i个物体的重量
- p[i]:第i个物体的价值
- c[i][j]:前i个物体放入容量为j 包的最大价值
- c[i-1][j]:前i个物体放入容量为j 包的最大价值
- c[i-1][j-w[i]]:前i-1个物体放入容量为j-w[i] 包的最大价值

以下通过表格来说状态转移方程
c[i][m]=max{c[i-1][m-w[i]]+p[i](m>w[i]) , c[i-1][m]}
这里写图片描述
首先明确该表是至底向上,从左到生成的。且上边abcde带代表编号5,4,3,2,1

  • c[3][2]代表 编号1,2,3三件物品放入容量为2的包中的最大价值。因为编号1,2,3的任一件物品的重量都要大于2,装入容量为2的包。即w[i]>2(i=1,2,3) 故c[3][2]=0
  • 现在通过思考c[5][8]=15的由来理解上式的状态转移方程
    • 根据c[i][m]=max{c[i-1][m-w[i]]+pi(m>w[i]) , c[i-1][m]}公式,需要考虑c[4][8-w[5]]+p[5]=9+6=15, c[4][8]=9, c[5][8]=15
      这里写图片描述
      当逐步推出表中每个值的大小,那个最大价值就求出来了。推导过程中,注意一点,最好逐行而非逐列开始推导,先从编号为1的那一行,推出所有c[1][m]的值,再推编号为2的那行c[2][m]的大小。这样便于理解。

以下开始用python编程

#n:物品件数;c:最大承重为c的背包;w:各个物品的重量;v:各个物品的价值#第一步建立最大价值矩阵(横坐标表示[0,c]整数背包承重):(n+1)*(c+1)#技巧:python 生成二维数组(数组)通常先生成列再生成行def bag(n,c,w,p):    res=[[-1 for j in range(c+1)]for i in range(n+1)]    for j in range(c+1):        #第0行全部赋值为0,物品编号从1开始.为了下面赋值方便        res[0][j]=0    for i in range(1:n+1):        for j in range(1:c+1):            res[i][j]=res[i-1][j]            #生成了n*c有效矩阵,以下公式w[i-1],p[i-1]代表从第一个元素w[0],p[0]开始取。            if(j>=w[i-1]) and res[i-1][j-w[i-1]]+p[i-1]>res[i][j]:                res[i][j]=res[i-1][j-w[i-1]]+p[i-1]    return res#以下代码功能:标记出有放入背包的物品#反过来标记,在相同价值情况下,后一件物品比前一件物品的最大价值大,则表示物品i#有被加入到背包,x数组设置为True。设初始为j=c。def show(n,c,w,res):      print('最大价值为:',res[n][c])      x=[False for i in range(n)]      j=c      for i in range(1,n+1):          if res[i][j]>res[i-1][j]:              x[i-1]=True              j-=w[i-1]      print '选择的物品为:'      for i in range(n):          if x[i]:              print '第',i,'个,'     print'' if __name__=='__main__':      n=5      c=10      w=[2,2,6,5,4]      p=[6,3,5,4,6]      res=bag(n,c,w,p)      show(n,c,w,res) 

爱奇艺算法题

这里写图片描述
这里写图片描述
这里写图片描述

该题与背包问题有以下等价

  • 节目数等价于物品数n
  • 采购预算金额B等价于背包承受总重c
  • 每个节目的价格P[i]等价于每个物品的重量w[i]
  • 每个节目的播放量V[i]等价于每个物品的价值p[i]
    现在解决的问题为总金额不超过B的前提下获得最高的预期值播放量?
    等价于不超过背包称重量c的前提下获得最高的物品价值?
    先输入流数据进行处理:
#转化为列表之后不能直接int(List)n=int(sys.stdin.readline().strip())#正确解法:需要对列表内每个数int();使用raw_input()不会读取回车,sys.stdin()会读取回车键dat=[int(x) for x in raw_input().strip().split()]c=dat[0];p=[];v=[]m=len(dat)for i in range(1,m,2):    p.append(dat[i])for j in range(2,m,2):    v.append(dat[j])

数据处理完后将对应的带入背包问题的bag函数中即可得到结果。

原创粉丝点击