问题:
假设有3, 1, 18, 11, 13, 17等6个数,不进行排序分为 bins = 4 箱,要求分箱后总开销最少。
注:每个箱子的开销为,x1,...xn(箱内元素)的和方差,空箱子的开销为+∞,比如一个箱子里放13和17两个数,avg = (13+17)/2 = 15,
则此箱子的开销cost = (13-avg)^2 + (17-avg)^2 ,就是求他们的和方差sse
解决方法:
1. 递归
import numpy as np
def sse(arr):
if len(arr) == 0: # deal with arr == []
return 0.0
avg = np.average(arr)
val = sum( [(x-avg)*(x-avg) for x in arr] )
return val
LARGE_NUM = 1000000000.0
def v_opt_rec(xx, b):
mincost = LARGE_NUM
n = len(xx)
# check boundary condition:
if n < b:
return LARGE_NUM + 1
elif b == 1:
return sse(xx)
else: # the general case
for t in range(n):
prefix = xx[0 : t+1]
suffix = xx[t+1 : ]
cost = sse(prefix) + v_opt_rec(suffix, b - 1)
print(' '*calc_depth(b),'mincost:',mincost,'cost:',cost)
mincost = min(mincost, cost)
return mincost
递归思路,把数字分成两部分,每次的cost 等于前部分的开销加后部分继续调用函数计算
cost = sse(prefix) + v_opt_rec(suffix, b - 1)
递归的方法优点是占用空间少、逻辑简单;缺点是计算效率不高,进行了多次重复计算
2. 动态规划
什么是动态规划?
很多人觉得动态规划复杂,其实用一句话就可以描述出其本质。动态规划的本质就是:记住已经解决过的子问题的解。
即,新的问题不在重复计算已经解决过的问题了。
比如计算斐波那契数列,用递归方法是,
def fib(x):
if x == 0 or x == 1:
return 1
else:
return fib(x-1)+fib(x-2)
如果你要计算fib(4),

可以看出,f(0),f(1), f(2)都被重复计算了,这样浪费了很多计算机资源
如果我们可以在首次计算f(0),f(1), f(2)时,就把其存储起来,第二次需要计算f(2)时