戳气球——动态规划

61 阅读1分钟

image.png

代码1,记忆化搜索:

  1. 在原切片 nums 前后各加一个位置,且值为 1 ,从而方便处理临界情况,处理过后的切片为val
  2. rec 二维切片进行记录值,从而达到记忆化递归的目的
  3. 递归参数,左下标,右下标,处理过的气球切片val,以及存储递归值的rec二维切片
  4. 递归结束条件,left不在right左边,因为递归进行了记忆化处理,所以在rec有值的情况下自然也可以直接返回
  5. for循环将所有情况计算,并且取最大值
  6. 最后返回最终的值 rec[left][right]
func maxCoins(nums []int) int {
    n := len(nums)
    val := make([]int, n + 2)
    for i := 1; i <= n; i++ {
        val[i] = nums[i - 1]
    }
    val[0], val[n+1] = 1, 1
    rec := make([][]int, n + 2)
    for i := 0; i < len(rec); i++ {
        rec[i] = make([]int, n + 2)
        for j := 0; j < len(rec[i]); j++ {
            rec[i][j] = -1
        }
    }
    return solve(0, n + 1, val, rec)
}

func solve(left, right int, val []int, rec [][]int) int {
    if left >= right - 1 {
        return 0
    }
    if rec[left][right] != -1 {
        return rec[left][right]
    }
    for i := left + 1; i < right; i++ {
        sum := val[left] * val[i] * val[right]
        sum += solve(left, i, val, rec) + solve(i, right, val, rec)
        rec[left][right] = max(rec[left][right], sum)
    }
    return rec[left][right]
}

func max(x, y int) int {
    if x > y {
        return x
    }
    return y
}

代码2,动态规划:

代码 1 自顶向下递归求值,自然也可以,自底向上动态规划求值,从构造小问题,一步一步还原出大问题

func maxCoins(nums []int) int {
    n := len(nums)
    rec := make([][]int, n + 2)
    for i := 0; i < n + 2; i++ {
        rec[i] = make([]int, n + 2)
    }
    val := make([]int, n + 2)
    val[0], val[n+1] = 1, 1
    for i := 1; i <= n; i++ {
        val[i] = nums[i-1]
    }
    for i := n - 1; i >= 0; i-- {
        for j := i + 2; j <= n + 1; j++ {
            for k := i + 1; k < j; k++ {
                sum := val[i] * val[k] * val[j]
                sum += rec[i][k] + rec[k][j]
                rec[i][j] = max(rec[i][j], sum)
            }
        }
    }
    return rec[0][n+1]
}

func max(x, y int) int {
    if x > y {
        return x
    }
    return y
}