题目

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

第一种思路,基于投资问题模型

从每种物品的角度考虑,与它相关的策略已并非取或不取两种,而是有取 0 件、取 1 件、取 2 件…直至取 ⌊V /C i ⌋ 件等许多种。

状态方程为:

F [i, v] = max {F [i − 1, v − kC i ] + kW i | 0 ≤ kC i ≤ v}

基于以上状态方式实现的三种方式,递归,自上而下,自下而上如下:

# another way: F [i, v] = max {F [i − 1, v − kC i ] + kW i | 0 ≤ kC i ≤ v}
def pack_complete_Rec2(N,V,C,W):if N ==0:return 0    k = V // C[N-1]result = -1for i in range(k+1):A = pack_complete_Rec2(N-1,V-i*C[N-1],C,W) + i*W[N-1]if A > result:result = Areturn result
import numpy as np
# 注意if list[N,V] == -1 的未知,因为它确定了剪枝;
def pack_complete_Top_down2(N,V,C,W):list = np.zeros((N+1,V+1),dtype=int)list[1:,:] = -1def complete_Top_down(N,V):t = V // C[N-1] if list[N,V] == -1 :result = -1000for k in range(t+1):if N >=1:A = complete_Top_down(N-1,V-k*C[N-1]) + k*W[N-1]if A >= result:result = Alist[N,V] = result return list[N,V]return complete_Top_down(N,V)
def pack_complete_Bottom_up2(N,V,C,W):list = np.zeros((N+1,V+1),dtype=int)
#    list[1:,:] = -1for i in range(1,N+1):for j in range(0,V+1):t = j // C[i-1]result = -1000for k in range(t+1):A = list[i-1,j-k*C[i-1]] + k*W[i-1]if A > result:result = Alist[i,j] = result         return list[N,V]

把问题转换成01背包问题,这里面涉及到等效或者泛化物品

将一种物品拆成多件只能选 0 件或 1 件的01背包中的物品,以下是简单实现,基于二进制的实现,在多重背包中实现:

# change complete to 01
def change_complete_to_01(N,V,C,W):C_ =[]W_ =[]for i in range(N):t = V // C[i]for k in range(1,t+1):C_.append(C[i])W_.append(W[i])def pack_0_1_first(N,V,C,W):    F =[0]*(V+1)    for i in range(1,N+1):for v in range(V,C[i-1]-1,-1):F[v] = max(F[v],F[v-C[i-1]] + W[i-1])return F[V]N_ = len(C_)return pack_0_1_first(N_,V,C_,W_)

更为简单的实现,把第i种物品看成一个整体,针对第i种物品就有2种策略,1不选:可以看成i-1的问题,二选,就可以看成第i类的01背包问题,因为V是一定的,此时的i实际上不是无限的,是受V限制的,就可以把有限的i看成不同的物品,等价于一个01背包问题,状态方程如下:

F [i, v] = max (F [i − 1, v], F [i, v − C i ] + W i )

基于以上状态方式实现的三种方式,递归,自上而下,自下而上如下:

def pack_complete_Rec(N,V,C,W):if N ==0:return 0if V < C[N-1]:return pack_complete_Rec(N-1,V,C,W)return max(pack_complete_Rec(N-1,V,C,W),pack_complete_Rec(N,V-C[N-1],C,W) + W[N-1])  import numpy as np
def pack_complete_Top_down(N,V,C,W):list = np.zeros((N+1,V+1),dtype=int)list[1:,:] = -1def complete_Top_down(N,V):if list[N,V] == -1 and N >=1:A = complete_Top_down(N-1,V)if V < C[N-1]: return Aelse:list[N,V] = max(A,complete_Top_down(N,V-C[N-1])+W[N-1])return list[N,V]return complete_Top_down(N,V)def pack_complete_Bottom_up(N,V,C,W):list = np.zeros((N+1,V+1),dtype=int)list[1:,:] = -1for i in range(1,N+1):for j in range(0,V+1):A = list[i-1,j]  if j < C[i-1]: list[i,j] = A  else:list[i,j] = max(A,list[i,j-C[i-1]]+W[i-1])return list[N,V]

基于一维数组的简单的实现如下,对比上述的Bottom_up方法,使用一维数组实现,通过初始化,能够有效避免,左边的走法:

def pack_complete_first(N,V,C,W):def CompletePack(F,ci,wi):for v in range(ci,V+1):F[v] = max(F[v],F[v-ci] + wi)return FF =[0]*(V+1)for i in range(1,N+1):CompletePack(F,C[i-1],W[i-1])return F[V]

完全背包可行性问题,只取决于初始化,只有F[0,0]才为0时,才可以得到有效解。

def pack_complete_first_yes_or_no(N,V,C):def CompletePack_or(F,ci,wi):for v in range(ci,V+1):F[v] = F[v] or F[v-ci]return FF =[False]*(V+1)F[0] = Truefor i in range(1,N+1):CompletePack_or(F,C[i-1],W[i-1])return F[V]def pack_complete_Bottom_up_yes_or_no(N,V,C):list = np.zeros((N+1,V+1),dtype=bool)list[0,0] = Truefor i in range(1,N+1):for j in range(0,V+1):A = list[i-1,j]  if j < C[i-1]: list[i,j] = A  else:list[i,j] = A or list[i,j-C[i-1]]return list[N,V]

运行结果:

#%%
N = 7
V = 77
C = [1,2,3,9,13,6,7,5]
W = [1,2,9,7,5,11,6,14]
#%%
print pack_complete_first(N,V,C,W)
print pack_complete_Rec(N,V,C,W)
print pack_complete_Top_down(N,V,C,W)
print pack_complete_Bottom_up(N,V,C,W)
print pack_complete_first_yes_or_no(N,V,C)
print pack_complete_Bottom_up_yes_or_no(N,V,C)
print pack_complete_Rec2(N,V,C,W)
print pack_complete_Top_down2(N,V,C,W)
print pack_complete_Bottom_up2(N,V,C,W)
print change_complete_to_01(N,V,C,W)227
227
227
227
True
True
227
227
227
227

完全背包问题从简单到复杂相关推荐

  1. 0-1背包问题的简单解释

    01背包问题,是用来介绍动态规划算法最经典的例子,网上关于01背包问题的讲解也很多,我写这篇文章力争做到用最简单的方式,最少的公式把01背包问题讲解透彻. 01背包的状态转换方程 f[i,j] = M ...

  2. java 简单背包问题_简单的背包问题--java递归实现

    1.主程序 package recursion; //简单背包问题-递归实现- //将不同重量的数据项放入背包中,以使背包的最后 //-----------达到指定的总重量------------- ...

  3. 01背包问题从简单到复杂

    题目: 有 N 件物品和一个容量为 V 的背包.放入第 i 件物品耗费的费用是 C i 1 ,得到 的价值是 W i .求解将哪些物品装入背包可使价值总和最大. 状态转移方程: F [i, v] = ...

  4. 背包问题九讲 v1.0

    背包问题九讲 v1.0 目录 第一讲 01背包问题 第二讲 完全背包问题 第三讲 多重背包问题 第四讲 混合三种背包问题 第五讲 二维费用的背包问题 第六讲 分组的背包问题 第七讲 有依赖的背包问题 ...

  5. c++ 多重背包状态转移方程_【模板】各种背包问题amp;讲解

    [模板]各种背包问题&讲解  背包问题集合 一般来说,动态规划(DP)都是初学者最难闯过的一关,而在这里详细解说动态规划的一种经典题型:背包问题. 这里介绍的背包分为以下几种:01背包,完全背 ...

  6. 经典动态规划:0-1 背包问题

    经典动态规划:0-1 背包问题 文章目录 经典动态规划:0-1 背包问题 一.题目描述 二.动规标准套路 三.题目描述 四.解法分析 五.优化 一.题目描述 就讨论最常说的 0-1 背包问题,简单描述 ...

  7. 算法随笔一(背包问题)

    今天逛园子,偶然看到了"背包问题",于是上网找了下相关资料,并写了个简单的实现方案. 何为背包问题? 简单理解,就是给了一堆物品跟一个包,每个物品都有相应的重量和价值,包有自己的承 ...

  8. 基因算法解析、设计,以解决背包问题和旅行商问题为例

    一.算法说明 基因算法 基因算法有一套公共的完整的框架,伪代码如下. beginset time t = 0 # first generationinitGeneration() # initiali ...

  9. 多重背包问题和“二进制拆分”

    预告:我用两年写的新书<算法竞赛>,已于2022年2月交给清华大学出版社,预计于2022年7月出版.<算法竞赛>是一本"大全",内容覆盖"基础-中 ...

最新文章

  1. 掌握这些步骤,机器学习模型问题药到病除
  2. python 静态变量 静态方法 简介
  3. 常用数据结构及复杂度
  4. #6029. 「雅礼集训 2017 Day1」市场(势能,区间除)
  5. 计算机二级web题目(8.3)--简单应用题2
  6. [AHOI2009]最小割(最大流+tarjan)
  7. Asp.Net母版页和内容页运行机制
  8. iPhone手机投屏小米盒子
  9. 如何减小Exe, DLL 的大小
  10. 在C#中列出进程,杀掉进程。
  11. 软件开发文档编写规范
  12. QT5安装自己下载的mingw32及一些常见报错解决
  13. 低功耗中的Isolation cells 和Level shifter cells
  14. Java实现HTML页面截图功能
  15. mysql MERGE 错误(differently defined or of non-MyISAM type)
  16. 跳槽理由—你的跳槽理由合理吗
  17. C语言字符串分割 trimmed simplified split
  18. ural 1104. Don’t Ask Woman about Her Age
  19. 服务器系统才有卷影副本吗,windows server 2019没有适合具有卷影副本的卷
  20. 计算机系微电子专业大学排名,2017微电子专业大学排名

热门文章

  1. 查看mongodb数据路径_Mac OS 中安装和使用 MongoDB 的方法
  2. springmvc执行流程(简述易懂)
  3. springboot配置热部署
  4. 错误:未在本地计算机上注册“Microsoft.Ace.OleDb.12.0”提供程序
  5. 淘宝NPM镜像、cnmp
  6. java ArrayList排序
  7. Servlet获取URL地址
  8. maven项目修改java编译版本的方式
  9. datagrid出现相同两组数据_数据分析之统计学
  10. java短_Java中的最短代码和最低延迟