312. 戳气球

16 篇文章 0 订阅

问题

在这里插入图片描述
在这里插入图片描述

例子

在这里插入图片描述

思路
回溯时间太久【第一次有n个选择,第二次有n-1个选择,时间为O(n!)】
动态规划【有最字】+分治
区间[i, j] 戳破的气球为k。
k戳破后,区间变成了[i, k) 和(k, j],即[i, i+1, … k-1, k+1, …j],那么k+1啥时候戳破对[i, k)的结果有影响,如果先戳破k-1,再戳破k+1,k-1的右边是k+1,计算时[k-2]*[k-1]*[k+1],如果先戳破,(k, j]中的k+1,再戳破[i, k)中的k-1,此时k-1右边的变成了k+2,计算时[k-2]*[k-1]*[k+2]
,即左右两边区间的计算产生了依赖。
如何不产生依赖呢?气球k,放在最后戳爆它。
k为区间[i, j]间最后一个戳爆的气球,它把[i, j]分为了[i, k-1]和[k+1, j]两个区间,可分别求出

  • 方法1
    状 态 转 移 方 程    d p [ i ] [ j ] 为 [ i , j ] 区 间 的 最 大 值 d p [ i ] [ j ] = m a x ( d p [ i ] [ k − 1 ] + d p [ k + 1 ] [ j ] + a r r [ i − 1 ] ∗ a r r [ k ] ∗ a r r [ j + 1 ] )    i < = k < = j 状态转移方程~~ dp[i][j]为[i,j]区间的最大值\\ dp[i][j]=max(dp[i][k-1]+dp[k+1][j]+arr[i-1]*arr[k]*arr[j+1]) ~~i<=k<=j   dp[i][j][i,j]dp[i][j]=max(dp[i][k1]+dp[k+1][j]+arr[i1]arr[k]arr[j+1])  i<=k<=j

  • 方法2
    $$

    $$

代码

//方法1 自顶向下
class Solution {
    public int maxCoins(int[] nums) {
        //创建虚拟边界
        int[] arr = new int[nums.length+2];
        System.arraycopy(nums,0,arr,1,nums.length);
        
        arr[0]=1;
        arr[arr.length-1]=1;
        
        int[][] dp = new int[arr.length][arr.length];
        return get(arr,1,arr.length-2,dp);

    }
    public int get(int[] arr,int i,int j, int[][] dp) {
        if(i>j) return 0;
        if(dp[i][j]>0) return dp[i][j];
        int max = 0;
        for(int k=i; k<=j; k++) {
            max = Math.max(max, arr[i-1]*arr[k]*arr[j+1]+get(arr, i,k-1,dp)+get(arr,k+1,j,dp));
        }
        dp[i][j]=max;
        return max;
    }
}
//方法2 自下而上
class Solution {
    public int maxCoins(int[] nums) {
        int n = nums.length;
        //创建虚拟边界
        int[] arr = new int[n+2];
        System.arraycopy(nums,0,arr,1,n);
        
        arr[0]=1;
        arr[n+1]=1;
        
        int[][] dp = new int[n+2][n+2];
        
        for(int len = 1; len<=n; len++) {
            for(int i=1; i+len-1<=n; i++) {
                int j = i+len-1;
                for(int k=i; k<=j; k++) {
                    dp[i][j]=Math.max(dp[i][j], arr[i-1]*arr[k]*arr[j+1]+dp[i][k-1]+dp[k+1][j]);
                }
            }
        }
        return dp[1][n];

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值