Burst Balloons

来源:互联网 发布:python爬虫书籍推荐 编辑:程序博客网 时间:2024/05/21 09:39

Description
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 right are 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:
(1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.
(2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100

Example:

Given [3, 1, 5, 8]

Return 167

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

解题思路:使用逆向思维解决这道题。假设f(i,j)表示炸掉编号为i到j的气球所能获得的最多硬币,先考虑最后炸掉的气球,如果最后炸掉的气球的编号为k,那么f(i,j)= f(i,k)+f(k,j)+ nums[k](i<=k<=j),因为在最后一步k能够取遍i到j的所有可能,但是在上一步比如计算f(i,k)或f(k,j)时,编号k的气球就不能够被选为要炸掉的气球,因此如果这一步要炸掉的气球的编号为k’ 时,k’ 的可能选择为(i<= k’ < k 或k< k ‘< j)。为了统一k的取值,先在这组气球的头和尾加入编号为i-1以及j+1的两个气球,令f’(i-1,j+1)表示炸掉编号区间为(i,j)的气球所能获得的最多硬币。其实也可以这么考虑,只要把f’(i,j)中的i和j号气球当成最后要炸的两个气球,那么在此之前要炸掉在(i+1,j-1)中的所有气球。令在头和尾加入的那两个气球代表的数目为1,f(i,j)=f’(i+1,j-1)=max{f’(i+1,k)+f’(k,j-1)+nums[i+1] * nums[k] * nums[j-1]}(i + 1< k < j - 1)。程序代码如下:

class Solution {public:    int maxCoins(vector<int>& nums) {        vector<vector<int>> dp(nums.size() + 2, vector<int>(nums.size() + 2, 0));        vector<int> n(nums.size() + 2, 1); //在头和尾加入两个气球后的数组        for (int i = 0; i < nums.size(); i++)            n[i + 1] = nums[i];        for (int len = 2; len <= n.size(); len++) {            for (int left = 0; left + len - 1 < n.size(); left++) {                int right = left + len - 1;                for (int i = left + 1; i < right; i++) {                    dp[left][right] = max(dp[left][right], n[left] * n[i] * n[right]                                           + dp[left][i] + dp[i][right]);                }            }        }        return dp[0][nums.size() + 1];    }};
原创粉丝点击