2021-04-16:摆放着n堆石子。现要将石子有次序地合并成一堆,规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。求出将n堆石子合并成一堆的最小得分(或最大得分)合

2021-04-16:摆放着n堆石子。现要将石子有次序地合并成一堆,规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。求出将n堆石子合并成一堆的最小得分(或最大得分)合并方案。

福大大 答案2021-04-16:

动态规划。

代码用golang编写。代码如下:

package main

import (
    "fmt"
    "math"
)

func main() {
    arr := []int{1, 4, 2, 3}
    ret := StoneMerge(arr)
    fmt.Println(ret)

}
func sum(arr []int) []int {
    N := len(arr)
    s := make([]int, N+1)
    s[0] = 0
    for i := 0; i < N; i++ {
        s[i+1] = s[i] + arr[i]
    }
    return s
}
func w(s []int, l int, r int) int {
    return s[r+1] - s[l]
}
func StoneMerge(arr []int) int {
    if len(arr) < 2 {
        return 0
    }
    N := len(arr)
    s := sum(arr)
    dp := make([][]int, N)
    for i := 0; i < N; i++ {
        dp[i] = make([]int, N)
    }
    best := make([][]int, N)
    for i := 0; i < N; i++ {
        best[i] = make([]int, N)
    }
    for i := 0; i < N-1; i++ {
        best[i][i+1] = i
        dp[i][i+1] = w(s, i, i+1)
    }
    for L := N - 3; L >= 0; L-- {
        for R := L + 2; R < N; R++ {
            next := math.MaxInt64
            choose := -1
            for leftEnd := best[L][R-1]; leftEnd <= best[L+1][R]; leftEnd++ {
                cur := dp[L][leftEnd] + dp[leftEnd+1][R]
                if cur <= next {
                    next = cur
                    choose = leftEnd
                }
            }
            best[L][R] = choose
            dp[L][R] = next + w(s, L, R)
        }
    }
    return dp[0][N-1]
}

执行结果如下:
图片


左神java代码
评论

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
将n堆石子合并一堆的规则是每次只能相邻石子堆进行合并。为了使合并次数最少,我们需要考虑如何相邻石子堆。 假设有4堆石子,分别有a、b、c、d颗石子。如果我们合并a和b堆,然后将堆和c堆合并,最后再将堆和d堆合并合并次数是a+b+c+d。但是如果我们先合并b和c堆,然后是a和合并后的bc堆,最后再与d合并合并次数是b+c+(a+bc)+d。 可以观察到,合并次数会受到合并顺序的影响。因此,我们需要根据石子堆的数量和石子堆的石子数量来确定合并的顺序。 设dp[i][j]表示合并从第i堆到第j堆石子所需的最小合并次数。那么有以下递推公式: dp[i][j] = min(dp[i][k] + dp[k+1][j] + sum[i][j]), k∈[i, j-1],其中sum[i][j]表示第i堆到第j堆石子的总数。 当i=j时,dp[i][j]为0,因为此时只有一堆石子,无需合并。当i<j时,dp[i][j]可以通过遍历k来得最小值。 具体操作是,首先初始化dp数组为0。然后从2堆石子开始,依次递增地计算合并次数。根据递推公式,遍历每个dp[i][j],通过计算dp[i][k] + dp[k+1][j] + sum[i][j]的值,更dp[i][j]的最小值。 最终,dp[1][n]的值即为将n堆石子合并一堆所需的最小合并次数。 例如,有4堆石子,分别有a、b、c、d颗。通过计算dp[1][4],可以得到将这4堆石子合并一堆的最小合并次数。 这样,我们可以利用动态规划的方法解决将n堆石子合并一堆的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

福大大架构师每日一题

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值