zoukankan      html  css  js  c++  java
  • leetcode312

    Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. Here left and rightare adjacent indices of i. After the burst, the left and right then becomes adjacent.
    Find the maximum coins you can collect by bursting the balloons wisely.
    Note:
    * You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.
    * 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100
    Example:
    Input: [3,1,5,8]
    Output: 167
    Explanation: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
    coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167

    DP。O(n^3)
    考虑消去型的dp,不好正面想消去后接下来怎么处理,要反过来想。先想最后一个消去的对象能得多少分,想最后一个对象消哪一个能让答案为最大值。
    本题有一个特点:左右区间独立。消去最后一个气球时,气球左边的区间消去最优得分和气球右边的区间完全没关系。这是因为两边的气球被中间这个气球隔开了,左边区间最后一个气球分数才用到中间这个气球,再左边的气球更用不到中间及以后的气球了。利用这个特性,如果我们在[i,j]这段区间中间的k位置扎破最后一个气球,那么得分关系就有point[i,j] = point[i,k] + point[k,j] + 扎k得分。

    dp[i][j]定义:区间[i, j]中扎气球能得的最大分数,保证i, j不被扎破。
    初始化:所有长度为2的区间如dp[i, i+1]都初始化为0,因为两个边缘气球不能被扎破。
    递推公式:dp[i][j] = Max(dp[i][k] + dp[k][j] + nums[i] * nums[k] * nums[j]), 对所有满足i < k < j 的k遍历。


    细节:
    1.区间型动态规划的推导顺序,最外层按区间长度循环渐增。然后内部先根据起始点i循环,由i和len可以直接得到j。i的循环条件根据j的下标要在什么范围内可以推得。
    2.最开始先对nums扩充一下左右两边比较好,也就是最左边和最右边有一个nums[i] == 1的不能扎破的气球,这样好算原始数据里最边缘两个气球被扎破时的得分。

    实现:

    class Solution {
        public int maxCoins(int[] nums) {
            if (nums == null || nums.length == 0) {
                return 0;
            }
            
            int[][] dp = new int[nums.length + 2][nums.length + 2];
            int[] temp = new int[nums.length + 2];
            temp[0] = temp[temp.length - 1] = 1;
            for (int i = 0; i < nums.length; i++) {
                temp[i + 1] = nums[i];
            }
            nums = temp;
            
            dp[0][0] = 0;
            for (int i = 1; i < dp.length; i++) {
                dp[i][i] = 0;
                dp[i - 1][i] = 0;
            }
            
            
            for (int dist = 2; dist <= dp.length - 1; dist++) {
                for (int i = 0; i + dist < dp[0].length; i++) {    
                    int j = i + dist;
                    dp[i][j] = 0;
                    for (int k = i + 1; k < j; k++) {
                        dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[k][j] + nums[i] * nums[k] * nums[j]);
                    }
                }
            }
            return dp[0][dp[0].length - 1];
            
        }
    }
  • 相关阅读:
    phoenix 开发API系列 目录
    phoenix 开发API系列(三)phoenix api 结合数据库
    phoenix 开发API系列(二)phoenix 各类 api 实现方式
    phoenix 开发API系列(一)创建简单的http api
    golang 远程传输文件
    PAT-2019年冬季考试-甲级 7-3 Summit (25分) (邻接矩阵存储,直接暴力)
    PAT-2019年冬季考试-甲级 7-2 Block Reversing (25分) (链表转置)
    PAT-2019年冬季考试-甲级 7-1 Good in C (20分)
    PAT 甲级 树专题小结
    PAT 甲级 1020 Tree Traversals (25分)(后序中序链表建树,求层序)***重点复习
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/9660227.html
Copyright © 2011-2022 走看看