动态规划-打靶子/戳气球

题目描述:

在某射击场有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 分析


猜你喜欢

转载自blog.csdn.net/m0_37541228/article/details/77360158
今日推荐