2021-04-29:给定一个数组 arr,代表一排有分数的气球。每打爆一个气球都能获得分数,假设打爆气 球 的分数为 X,获得分数的规则如下: 1)如果被打爆气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为 L;如果被打爆气球的右边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为 R。 获得分数为 LXR。 2)如果被打爆气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为 L;如果被打爆气球的右边所有气球都已经被打爆。获得分数为 LX。 3)如果被打爆气球的左边所有的气球都已经被打爆;如果被打爆气球的右边有没被打爆的 气球,找到离被打爆气球最近的气球,假设分数为 R;如果被打爆气球的右边所有气球都 已经 被打爆。获得分数为 XR。 4)如果被打爆气球的左边和右边所有的气球都已经被打爆。获得分数为 X。目标是打爆所有气球,获得每次打爆的分数。通过选择打爆气球的顺序,可以得到不同的总分,请返回能获得的最大分数。【举例】arr = {3,2,5} 如果先打爆3,获得32;再打爆2,获得25;最后打爆5,获得5;最后总分21 如果先打爆3,获得32;再打爆5,获得25;最后打爆2,获得2;最后总分18 如果先打爆2,获得325;再打爆3,获得35;最后打爆5,获得5;最后总分50 如果先打爆2,获得325;再打爆5,获得35;最后打爆3,获得3;最后总分48 如果先打爆5,获得25;再打爆3,获得32;最后打爆2,获得2;最后总分18 如果先打爆5,获得25;再打爆2,获得32;最后打爆3,获得3;最后总分19 返回能获得的最大分数为50。
福大大 答案2021-04-29:
动态规划。
代码用golang编写。代码如下:
package main import ( "fmt" ) func main() { arr := []int{2, 2, 2} ret := maxCoins1(arr) fmt.Println(ret) ret = maxCoins2(arr) fmt.Println(ret) } func maxCoins1(arr []int) int { if len(arr) == 0 { return 0 } if len(arr) == 1 { return arr[0] } N := len(arr) help := make([]int, N+2) help[0] = 1 help[N+1] = 1 for i := 0; i < N; i++ { help[i+1] = arr[i] } return process(help, 1, N) } // 打爆arr[L..R]范围上的所有气球,返回最大的分数 // 假设arr[L-1]和arr[R+1]一定没有被打爆 func process(arr []int, L int, R int) int { if L == R { // 如果arr[L..R]范围上只有一个气球,直接打爆即可 return arr[L-1] * arr[L] * arr[R+1] } // 最后打爆arr[L]的方案,和最后打爆arr[R]的方案,先比较一下 max := getMax(arr[L-1]*arr[L]*arr[R+1]+process(arr, L+1, R), arr[L-1]*arr[R]*arr[R+1]+process(arr, L, R-1)) // 尝试中间位置的气球最后被打爆的每一种方案 for i := L + 1; i < R; i++ { max = getMax(max, arr[L-1]*arr[i]*arr[R+1]+process(arr, L, i-1)+process(arr, i+1, R)) } return max } func maxCoins2(arr []int) int { if len(arr) == 0 { return 0 } if len(arr) == 1 { return arr[0] } N := len(arr) help := make([]int, N+2) help[0] = 1 help[N+1] = 1 for i := 0; i < N; i++ { help[i+1] = arr[i] } dp := make([][]int, N+2) for i := 0; i < N+2; i++ { dp[i] = make([]int, N+2) } for i := 1; i <= N; i++ { dp[i][i] = help[i-1] * help[i] * help[i+1] } for L := N; L >= 1; L-- { for R := L + 1; R <= N; R++ { ans := help[L-1]*help[L]*help[R+1] + dp[L+1][R] ans = getMax(ans, help[L-1]*help[R]*help[R+1]+dp[L][R-1]) for i := L + 1; i < R; i++ { ans = getMax(ans, help[L-1]*help[i]*help[R+1]+dp[L][i-1]+dp[i+1][R]) } dp[L][R] = ans } } return dp[1][N] } func getMax(a int, b int) int { if a > b { return a } else { return b } }
执行结果如下: