zoukankan      html  css  js  c++  java
  • 动态规划-最佳加法表达式V2

    最佳加法表达式V2
    描述
    给定n个1到9的数字,要求在数字之间摆放m个加号(加号两边必须有数字),使得所得到的
    加法表达式的值最小,并输出该值。例如,在1234中摆放1个加号,最好的摆法就是12+34,和为36
    输入
    有不超过15组数据
    每组数据两行。第一行是整数m,表示有m个加号要放( 0<=m<=50)
    第二行是若干个数字。数字总数n不超过50,且 m <= n-1
    输出
    对每组数据,输出最小加法表达式的值
    样例输入
    2
    123456
    1
    123456
    4
    12345
    样例输出
    102
    579
    15

    递推实现:dp[i][j]表示j个加号插入i个数的最小加法表达式。为了计算方便,第0行增加多个最大值,
    i表示有多少个数字,j列表示有多少个加号
    这里假设最大值是999999.
    举例:3个加号,"12345"5个数字
    递推的步骤:先计算每一行的第1列,没有放入加号最小值的情况。
    第2次循环,计算每行,有1个加号最小值的情况;
    第3次循环,计算每行有2个加号最小值的情况;
    第4次循环,计算每行有3个加号最小值的情况;
    举个数据说明:比如dp[4][2]=19的计算过程,表示4个数字,插入2个加号
    那么这个k的值只有2或者3可以选择。
    当如果是2时,表示“12”插入1个加号的最小值+34,因此等于dp[2][1]+34=37
    当如果是3时,表示“123”插入1个加号的最小值+4,因此等于dp[3][1]+4=19,
    19的值最小,因此dp[4][2]=19
    因为我们都是把加入1个加号的最小值都计算出来了,当计算加入2个加号的时候,就可以利用
    上1个加号的最小值,从而实现递推第2个加号的最小值。
    通过不断的递推,二维列表的最后一行一列的值,既是整个表达式所求的最小值。
    # matrix_value[i][j]表示数字串num_list[N]的第i位到第j位之间的数字串表示的数组
    # 把输入的数字字符串,把每个位置数字的值存在二维数组,假设m=3,n=12345,
    # 为了方便从1开始计算,所以多增加0为第一行,其数组内容为:
    [[0, 0, 0, 0, 0, 0],
    [0, 1, 12, 123, 1234, 12345],
    [0, 0, 2, 23, 234, 2345],
    [0, 0, 0, 3, 34, 345],
    [0, 0, 0, 0, 4, 45],
    [0, 0, 0, 0, 0, 5]]
    dp[i][j] 表示前i个数字放入j个加号的最小加法表达式值
    [[999999, 999999, 999999, 999999],
    [1, 999999, 999999, 999999],
    [12, 3, 999999, 999999],
    [123, 15, 6, 999999],
    [1234, 46, 19, 10],
    [12345, 168, 51, 24]]

    python算法实现:
     1 def main():
     2     # m个加号
     3     m = int(input())
     4     # numList把数组字符串转换为列表
     5     num_list = list(str(input()))
     6     # n个数字
     7     n = len(num_list)
     8     # 把n个数字的值存在一个二维数组中
     9     matrix_value = [[0] * (n+1) for i in range(n+1)]
    10     #dp[i][j] 表示前i个数字放入j个加号的最小加法表达式值
    11     dp = [[999999] * (m+1) for i in range(n+1)]
    12     num_list = [int(i) for i in num_list]
    13     #为了遍历从1开始计算,所以在前面再增加个0
    14     num_list.insert(0, 0)
    15     # matrix_value二维数组存储字符串数字构成的各种数值
    16     for i in range(1,len(num_list)):
    17         for j in range(i,len(num_list)):
    18             matrix_value[i][j] = matrix_value[i][j - 1] * 10 + num_list[j]
    19         # i表示有几个数字,0表示没有加号的情况,比如dp[2][0]表示,2个数字0个加号表达式的值
    20         dp[i][0] = matrix_value[1][i]
    21 
    22     #递推
    23     #遍历加号个数,从放1个加号开始递增,m个加号
    24     for j in range(1,m+1):
    25         #遍历2个、3个……直到n个数字,保证数字个数大于加号个数,求其表达式的加法最小值
    26         #比如,放1个加号,至少需要2个数字,所以数字的个数i=j+1
    27         for i in range(j+1,n+1):
    28             #在有i个数字的情况下遍历最后一个加号可能的位置,k表示在第k个数后放加号
    29             #因为dp[k][j-1]之前已经计算好了,表示在k这个位置放入看j-1个加号
    30             #的最小值之前已经计算过,所以能直接使用,即递推的原理。
    31             # 这里k表示放最后一个加号的位置因为可能有很多个,所以需要遍历找到最小值的那个
    32             for k in range(j,i):
    33                 dp[i][j] = min(dp[i][j], dp[k][j-1] + matrix_value[k+1][i])
    34 
    35     print("加法最佳表达式的最小值:%.2f"%dp[-1][-1])
    36 
    37 
    38 if __name__ == '__main__':
    39     main()
  • 相关阅读:
    luogu 2617
    BZOJ 3295
    BZOJ 2458
    luogu 3810
    Uva
    Uva
    Uva
    Uva
    Uva
    成员函数的const到底修饰的是谁
  • 原文地址:https://www.cnblogs.com/an-wl/p/12994472.html
Copyright © 2011-2022 走看看