题目1 打气球的最大分数
-
题目描述
给定一个数组arr,长度为n。代表排有分数的气球。 每打爆一个气球都能获得分数,假设打爆气球的分数为X,获得分数的规则如下:
1)如果被打爆气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为L:如果被打爆气球的右边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为R.获得分数为LXR
2)如果被打爆的气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为L:如果被打爆气球的右边所有气球都已经被打爆,获得分数为LX。
3)如果被打爆气球的左边所有的气球都已经被打爆:如果被打爆气球的右边有没被打爆的气球,找到离被打爆气球最近的气球。获得分数为XR.
4)如果被打爆气球的左边和右边所有的气球都已经被打爆。获得分数为X。
目标是打爆所有气球,获得每次打爆的分数。通过选择打爆气球的顺序,可以得到不同的总分,请返回能获得的最大分数。 -
暴力递归解法
递推过程
尝试打爆arr[L, R]范围上的所有气球,并假设arr[L - 1]和arr[R + 1]没有被打爆,尝试过程process(L, R)
(1)arr[L]是最后一个被打爆的气球,先打arr[L + 1, R] <-- process(L + 1, R)
,再打arr[L]
由于arr[L + 1, R]打完,剩下arr[L]最左最右未打的是arr[L - 1]和arr[R + 1]
score = arr[L] * arr[L - 1] * arr[R + 1] + process(L + 1, R)
(2)arr[L + 1]是最后一个被打爆的气球,先打arr[L] <-- process(L, L)
,arr[L + 2, R] <-- process(L + 2, R)
,再打arr[L + 1]
由于剩下arr[L - 1]最左最右未打的是arr[L - 1]和arr[R + 1]
score = arr[L + 1] * arr[L - 1] * arr[R + 1] + process(L, L) + process(L + 2, R)
(3)…
(4)arr[i]是最后一个被打爆的气球,先打arr[L,i - 1] <-- process(L, i - 1)
,arr[i + 1, R] <-- process(i + 1, R)
,再打arr[i]
由于剩下的arr[i]最左最右未打的是arr[L- 1]和arr[R + 1]
score = arr[i] * arr[L - 1] * arr[R + 1] + process(L, i - 1) + process(i +1, R)
(5)arr[R]是最后一个被打爆的气球,先打arr[L,R - 1] <--process(L, R - 1)
,再打arr[R]
由于剩下的arr[R]最左最右未打的是arr[L- 1]和arr[R + 1]
score = arr[R] * arr[L - 1] * arr[R + 1] + process(L, R - 1)
arr = [3, 2, 5] 生成辅助数组help = [1, 3, 2, 5, 1]
public static int process(int[] arr, int L, int R){
//base case
if(L == R){
return arr[L] * arr[L - 1] * arr[R + 1];
}
//最后打爆arr[L]和arr[R]
//最后打arr[L]
int last_L = arr[L] * arr[L - 1] * arr[R + 1] + process(arr, L + 1, R);
//最后打arr[R]
int last_R = arr[R] * arr[L - 1] * arr[R + 1] + process(arr, L, R - 1);
int max = Math.max(last_L, last_R);
//普遍情