题目描述:
在某射击场有N个靶,每个靶上都有一个分数,存在score数组中。击中第i个靶的得分为score[left] * score[i] * score[right],同时原left和right两个靶变为相邻的靶。其中得分为0的靶是不能射击的,当left不存在或者不能射击时,得分为 score[i] * score[right],同理right也遵循此规则; 当left和right都不存在或者不能射击时,得分为score[i]。请计算出击中所有能射击的靶,最多能得多少分?设计算法。
输入描述:
靶子数量n 各个靶子的分数
输出:击中所有靶子所得分数
输入范例:
4
2
3
0
3
输出范例:
12
代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int arr[] = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = in.nextInt();
}
in.close();
System.out.println(getScore(arr, 0, n - 1));
}
public static int getScore(int[] score, int start, int end) {
if (score == null || start > end) {
return 0;
}
int n = end - start + 1;
for (int i = start; i < end; i++) {
if (score[i] == 0) {
return getScore(score, start, i - 1)
+ getScore(score, i + 1, end);
}
}
// 将score数组移到新的数组,在前后分别加一个值为1的数
int[] arr = new int[n + 2];
for (int i = start + 1; i <= end + 1; i++) {
arr[i - start] = score[i - 1];
}
arr[0] = arr[n + 1] = 1;
int[][] dp = new int[n + 2][n + 2];
int m = n + 2;
for (int k = 2; k < m; k++) {// 左右下标差,k=2表示left和right中间隔1个
for (int left = 0; left < m - k; ++left) {
int right = left + k;
for (int i = left + 1; i < right; ++i) {// 击中第i个靶
dp[left][right] = Math.max(dp[left][right], arr[left]
* arr[i] * arr[right] + dp[left][i] + dp[i][right]);
// 表示最后一个击中的是i号靶时的最大成绩
// left right中间的分数等于 最后剩i号靶时 i号靶分数是arr[left]* arr[i] *
// arr[right]
// left 到 i 号靶之间分数是dp[left][i] i到right之间分数是dp[i][right]
// 把所有i遍历一遍取最大值
}
}
}
return dp[0][m - 1];
}
}
参考博客: leetcode 312. Burst Balloons 分析