01背包问题
一. 问题描述
有n 个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?(人话就是:一个小偷去商店偷东西,但是由于带来的袋子不够大,装不完所有的东西,那就怎么可以偷到又多又值钱的东西)
二. 总体思路
根据动态规划解题步骤(问题抽象化、建立模型、寻找约束条件、判断是否满足最优性原理、找大问题与小问题的递推关系式、填表、寻找解组成)找出01背包问题的最优解以及解组成,然后编写代码实现;
三.动态的原理和实现
1.原理
动态规划就是把大问题拆解成小问题,寻找出大问题和小问题的递推关系,解决一个个小问题,从而解决原问题。而且动态规划只有记忆性,小问题的答案会被记住,避免在之后的小问题重复计算,节省了时间。
2.例子
B(k, w)在重量要少于w的情况下,选k的商品能偷到多少价值。
先列举商品,商品以着从小到大的顺序
k | 1 | 2 |
---|---|---|
w(重量) | 2 | 3 |
v(价值) | 3 | 4 |
然后可以在上述物品的条件下,B(k,w)在k从0到2,v从0到5的情况下对应的值
k/w | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
1 | 0 | 3 | 3 | 3 | 3 |
2 | 0 | 3 | 4 | 4 | 7 |
可能会有点懵。例如B(1,1)从前1个商品中选商品,但是背包容量只能小于等于1的倾向,背包里装的对应的价值应该是多少。
B(2,2)就是要从前2个商品中选出商品,但是背包容量只能小于等于2,背包里装的对应的价值应该是多少。
2.延伸
从上面的例子可以看出当挑选低第K个样品时,有两个选择
- w< w k w_k wk,不偷,这时候B(k,w)=B(k-1,w),价值一样(w是袋子里的空间,由于没偷袋子的空间也不会少)。
- w> w k w_k wk 的时候要就考虑好,不偷的时候的价值B(k-1,w)和偷的时候的价值B(k-1,w - w k w_k wk)+ v i v_i vi。
这样在2中就形成一个递推,就可以推回到我们上面那个简单的例子,从而知道做出抉择。
从k到k-1。。。1这样,都是上面的选择。从而达到解决这个问题。
代码也很简单:
name = ['a','b','c','d','e']
weight = [2,3,6,5,4]
value = [3,4,5,7,6]
volume = 10
def knapsack(n,w,v,c):
#建立一个矩阵来记录
m = np.zeros((len(n)+1, c+1))
for i in range(1,m.shape[0]):
for j in range(1, m.shape[1]):
if j < w[i-1]:
m[i,j] = m[i-1,j]
else:
m[i,j] = max([m[i-1,j], m[i-1, j-w[i-1]]+v[i-1]])
return m[len(name),c]
knapsack(name,weight,value,volume)
132
解题思路:
目前想不到方法,我看了其他人的discussion,我推理出这个逻辑再补上去
class Solution:
def minCut(self, s):
"""
:type s: str
:rtype: int
"""
if not s:
return 0
s_len = len(s)
mem = [i for i in range(-1, s_len)]
for i in range(1, s_len+1):
for j in range(i):
if s[j:i] == s[j:i][::-1]:
mem[i] = min(mem[i], mem[j] + 1)
return mem[-1]