合并金币

Posted WINNER_QIUQIU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了合并金币相关的知识,希望对你有一定的参考价值。

题目

N N N堆金币排成一排,第 i i i堆中有 C [ i ] C[i] C[i]块金币。每次合并都会将相邻的两堆金币合并为一堆,成本为这两堆金币块数之和。经过 N − 1 N-1 N1次合并,最终将所有金币合并为一堆。请找出将金币合并为一堆的最低成本。
其中, 1 ≤ N ≤ 30 , 1 ≤ C [ i ] ≤ 100 1\\leq N\\leq 30, 1\\leq C[i]\\leq 100 1N30,1C[i]100

分析:
这是一道区间动态规划问题,所谓区间动态规划就是求解一段区间上的最优解。主要是通过合并小区间的最优解进而得出整个大区间上最优解的动态规划算法。
详细介绍可参照此篇文章:区间dp入门
思路如下:首先声明一个N*N的二维列表,用于存放dp的值。利用第一个循环找出最开始两堆金币进行合并的所有情况。以算例一为例,那么可能出现:
dp[0][1]=C[0]+C[1]
dp[1][2]=C[1]+C[2]
dp[2][3]=C[2]+C[3]
要求解一个区间中的最优解,那么可以把这个区间分割成一个个小区间,求解每个小区间的最优解再合并为大区间即可。具体代码如下:

print("请输入金币的堆数:")
N = int(input())
print("请输入每堆中金币的数量:")
C = list(map(int,input().split()))

# 生成N*N内容为0的列表
dp = []
for i in range(N):
    list1 = []
    for j in range(N):
        list1.append(0)
    dp.append(list1)

#每次只有两堆金币进行合并会出现以下情况
for i in range(N-1): 
    dp[i][i+1] = C[i]+C[i+1]

#在小区间中求解最优解 
for i in range(N-1)[::-1]: 
    for j in range(i+1, N): 
        dp[i][j] = dp[i][i] + dp[i+1][j] + sum(C[i:j+1])
        for k in range(i, j): #枚举分割点,更新小区间最优解
            dp[i][j] = min(dp[i][k]+dp[k+1][j] + sum(C[i:j+1]), dp[i][j])

print(dp[0][-1])

输入描述:
第一行输入一个数字N表示有N堆金币
第二行输入N个数字表示每堆金币的数量C[i]
输出描述:
输出一个数字 s s s表示最小的合并成一堆的成本
算例一:
输入:
4
3 2 4 1
输出:
20
算例二:
输入:
30
10 20 30 40 50 60 70 80 90 100 99 89 79 69 59 49 39 29 19 9 2 12 22 32 42 52 62 72 82 92
输出:
7307

题目来源:美团2020校招系统开发方向笔试题

以上是关于合并金币的主要内容,如果未能解决你的问题,请参考以下文章

noip模拟赛 捡金币

问答项目---金币经验奖励规则及网站配置写入config文件

dp-简单迷宫捡金币

分金币

1-4金币阵列问题

2015金币