问题:
输入一个数字组成的字符串,给m个加号,将所有加号任意放在字符串中中某位置,要求最终得到的加法表达式的结果最小。
例子:
输入:2
123456
输出:135
思路:
我们用加号的个数作为迭代的依据。创建两个二维数组。
第一个是cur_min[m][n]表示将m个+号放入前n个数字中。根据加法式子的构成我们可以得到两个条件。1.m=0,即+号个数为0时,剩下的所有前面数字组成的数就是结果. 2. n>m+1,数字的个数一定比加号多一个,不然加法式子不成立
第二个是nums[n][n]代表所有从n到n的数字的大小。比如123456中n[1][3] = 234
在计算过程中首先循环计算前1到n个数字中插入0个加号的大小,等于nums[0][i]
再逐渐加入+。每次加入加号,可以加入的位置都是在m到n-1,因为数字个数必须要比+的个数多1
迭代转换方程式: cur_min[m][n] = min(cur_min[i][j],cur_min[i-1][p]+nums[p+1][j]) for p = i 到 j
举例说明迭代转化方程式比如求4个数字1234插入两个加号的最小值。就要先循环算+,p=2 to 3,
p=2就是cur_min[i-1][p]=1+2; nums[p+1][j] =34
p=3就是cur_min[i-1][p]=12+3和1+23中的最小的那个,即15; nums[p+1][j] =4
找出最小就是19
代码:
def best_add(m,ints):
nums = [[2**11 for i in range(len(ints))] for j in range(len(ints))]
for i in range(len(ints)):
nums[i][i] = ints[i]
for i in range(len(ints)):
for j in range(i+1,len(ints)):
nums[i][j] = nums[i][j-1]*10+ints[j]
cur_min = [[2**11 for i in range(len(ints))] for j in range(m+1)]
for i in range(len(ints)):
cur_min[0][i] = nums[0][i]
for i in range(1,m+1):
for j in range(len(ints)):
for p in range(i,j):
cur_min[i][j] = min(cur_min[i][j],cur_min[i-1][p]+nums[p+1][j])
return cur_min[m][len(ints)-1]
def main():
m = int(input())
nums=list(str(input()))
nums = [int(i) for i in nums]
print(best_add(m,nums))
if __name__ == '__main__':
main()