312-戳气球

1.自顶向下的递归+记忆化搜索

class Solution {
    int[] val;
    int[][] rec;
    public int maxCoins(int[] nums) {
        /**
        自顶向下的递归 + 记忆化搜索
        思想:逆向思维!
                将删除的过程反过来,每次向数组中添加元素并计算每次获得的硬币数
         */
        int n = nums.length;
        //给数组2边增加1
        val = new int[n+2];
        for(int i = 0;i < n;i++){
            val[i+1] = nums[i];
        }
        val[0] = val[n+1] = 1;

        rec = new int[n+2][n+2];
        for(int i = 0;i < n+2;i++){
            Arrays.fill(rec[i], -1);
        }
        return solve(0, n+1);
    }

    private int solve(int left, int right){
        if(left + 1 >= right){
            return 0;
        }
        if(rec[left][right] != -1){
            return rec[left][right];
        }
        for(int i = left+1;i < right;i++){
            int sum = val[left] * val[i] * val[right];
            sum += solve(left, i) + solve(i, right);
            rec[left][right] = Math.max(rec[left][right], sum);
        }
        return rec[left][right];
    }
}

2.自底向上的动态规划

class Solution {
    public int maxCoins(int[] nums) {
        //自底向上的动态规划
        int n = nums.length;
        int[] val = new int[n+2];
        for(int i = 0;i < n;i++){
            val[i+1] = nums[i];
        }
        val[0] = val[n+1] = 1;
        //dp[i][j]代表填满区间(i,j)能获得的最大硬币数 dp[i][j] = max{val[i]*val[k]*val[j]+dp[i][k]+dp[k][j]}, k∈(i, j) 
        int[][] dp = new int[n+2][n+2];

        for(int i = n-1;i >= 0;i--){
            for(int j = i+2;j < n+2;j++){
                for(int k = i+1;k < j;k++){
                    int sum = val[i] * val[k] * val[j];//实际上选出了后取哪一个k
                    sum += dp[i][k] + dp[k][j];
                    dp[i][j] = Math.max(dp[i][j], sum);
                }
            }
        }
        return dp[0][n+1];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值