将n根绳子分为最长的m根

问题:

有n根长度不等的绳子,允许剪短不允许拼接,将其分为等长的m根,求m根绳子的最大长度?
 

考虑用动态规划的方法:

$f(x_1, x_2, \dots, x_n, m) $为将$[x_1, x_2, \dots, x_n]$分为$m$个的最大长度。

则有以下动态转移方程:

$$ f(x_1, x_2, \dots, x_n, m)= max\left\{ \begin{align*} f(x_{n}, m)\\ min(f(x_1, x_2, \dots, x_{n-1}, 1), x_n/(m-1))\\ min(f(x_1, x_2, \dots, x_{n-1}, 2), x_n/(m-2))\\ \dots \\ min(f(x_1, x_2, \dots, x_{n-1}, m-1), x_n/1)\\ f(x_1, x_2, \dots, x_{n-1}, m)\\ \end{align*} \right. $$

Python代码如下:

#coding: utf-8

def maximum_rope(arr, m):
    n = len(arr)
    d = [[0 for i in range(m+1)] for j in range(n)]
    for i in range(1, m+1):
        d[0][i] = arr[0] / i
    print(d)
    temp = []
    for i in range(1, n):
        for j in range(1, m+1):
            for k in range(1, j):
                temp.append(min(d[i-1][k], arr[i]/(j-k)))
                # print('i:', i, 'j:', j, temp)
            temp.append(d[i-1][j])
            temp.append(arr[i]/j)
            d[i][j] = max(temp)
            temp = []
        print(d[i])
    print(d)
    return d[-1][-1]

aa = [4, 3, 5]
print(maximum_rope(aa, 6))

算法复杂度分析,用一个n*(m+1)的矩阵表示了状态转移过程,需要填每一个元素,所以需要计算n*(m+1)个元素,对于每一个元素的填入需要从k(1->m+1)个元素里面筛选,故算法复杂度为$o(n^3)$

 

算法心得:

在动态规划中对于当前的结果,当加入新的元素时可以用前面已经得到的结果,所以算法看起来复杂度很高,但如果绳子x和分的个数是一个动态增加的量,则可以用以前计算的结果,从而每次只需要$o(n^2)$的复杂度。所以对于输入是动态增加的问题,动态规划有此优势。

扩展:

基于当前计算结果计算新的结果这种思想能否用于强化学习。

debug:

Python中二维数组的声明:

d = [ [0] *n for i in range(m)]

错误类型, d = [[0] * n] * m

因为[0]*n是一个类的实例,再乘m是这个实例的m次引用,是同一个对象。

你可能感兴趣的:(算法,python)