题目描述
给定一个数组arr,长度为n。代表排有分数的气球。 每打爆一个气球都能获得分数,假设打爆气球的分数为X,获得分数的规则如下:
1)如果被打爆气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为L:如果被打爆气球的右边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为R.获得分数为L*X*R
2)如果被打爆的气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为L:如果被打爆气球的右边所有气球都已经被打爆,获得分数为L*X。
3)如果被打爆气球的左边所有的气球都已经被打爆:如果被打爆气球的右边有没被打爆的气球,找到离被打爆气球最近的气球。获得分数为X*R.
4)如果被打爆气球的左边和右边所有的气球都已经被打爆。获得分数为X。
目标是打爆所有气球,获得每次打爆的分数。通过选择打爆气球的顺序,可以得到不同的总分,请返回能获得的最大分数。
思路
动态规划。
假设当前目标是打破[L…R]上的气球,且L-1和R+1位置上的气球都没有破。设dp[L][R]为打破[L…R]上气球的最大分数。方法是考虑这个区间上最后一个气球的打破方式,即最后一个气球的打破位置。
根据最后一个气球的打破位置,有以下几种情况:
- 最后一个气球在L位置上,说明先打破了[L+1…R]位置上的气球,获得的分数为dp[L+1][R]。此时这个气球左边的气球就是L-1位置上的气球,右边的气球就是R+1位置上的气球。所以打破[L…R]上气球的最大分数就是arr[L-1]*arr[L]*arr[R+1]+dp[L+1][R]。
- 最后一个气球在i位置上,L+1<=i<=R-1,说明先打破了[L…i-1]位置上和[i+1…R]的气球,获得的分数为dp[L][i-1] + dp[i+1][R]。此时这个气球左边的气球就是L-1位置上的气球,右边的气球就是R+1位置上的气球。所以打破[L…R]上气球的最大分数就是arr[L-1]*arr[i]*arr[R+1]+dp[L][i-1]+dp[i+1][R]。
- 最后一个气球在R位置上,说明先打破了[L…R-1]位置上的气球,获得的分数为dp[L][R-1]。此时这个气球左边的气球就是L-1位置上的气球,右边的气球就是R+1位置上的气球。所以打破[L…R]上气球的最大分数就是arr[L-1]*arr[R]*arr[R+1]+dp[L][R-1]。
因为题目要求的是最大分数,所以应该是上述R-L+1种情况的最大值。
求dp数组时,应该先在纸上画出二维表格,标记出哪些位置应该求,进一步标记出一个位置的求解依赖于哪些位置,然后从最初始的位置进行求解。
因为要求整个dp数组,每个位置的求解复杂度又是O(n),所以总的时间复杂度为O(n^3)。
代码实现
import java.util.Scanner;
public class Main{
public static void main(String []args){
Scanner scanner = new Scanner(System.in);