Given
n
balloons, indexed from0
ton-1
. Each balloon is painted with a number on it represented by arraynums
. You are asked to burst all the balloons. If the you burst ballooni
you will getnums[left] * nums[i] * nums[right]
coins. Hereleft
andright
are adjacent indices ofi
. After the burst, theleft
andright
then becomes adjacent.
Find the maximum coins you can collect by bursting the balloons wisely.
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
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
解釋下題目:
給定一個數(shù)組,然后移除一個數(shù)字,這個數(shù)字和它左邊,它右邊的數(shù)字,這三個數(shù)字乘起來就是你能得到的分值,然后繼續(xù)往復(fù),直到把全部的氣球打掉,求出最大的分值。
1. DP
實(shí)際耗時:6ms
public int maxCoins(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
// init new array
int[] num = new int[nums.length + 2];
num[0] = 1;
num[nums.length + 1] = 1;
for (int i = 0; i < nums.length; i++) {
num[i + 1] = nums[i];
}
System.out.println(Arrays.toString(num));
// start dp
int[][] dp = new int[num.length][num.length];
for (int i = 2; i < num.length; i++) {
for (int left = 0; left < num.length - i; left++) {
int right = left + i;
for (int j = left + 1; j < right; j++)
dp[left][right] = Math.max(dp[left][right], num[left] * num[j] * num[right] + dp[left][j] + dp[j][right]);
}
}
return dp[0][num.length - 1];
}
??這是我做過的比較難的DP題目了。拿到題目首先想到的是用暴力。暴力的話,相當(dāng)于時間復(fù)雜度是O(n!),這顯然是不能接受的,肯定需要優(yōu)化,所以當(dāng)時想的是,因?yàn)樽钚〉臄?shù)字乘起來肯定是虧的,所以我想的是找到整個數(shù)組中最小的數(shù),然后把它打掉,,這樣就能有效減少遍歷次數(shù);但是!這是不可行的,樣例就是一個反例.....所以這種方法放棄,故只能轉(zhuǎn)而尋找動態(tài)規(guī)劃的方法。
??其實(shí)動態(tài)規(guī)劃也想了半天,下不去手,因?yàn)閷?shí)在選不出應(yīng)該先打破哪個氣球,主要是你打破任意一個氣球之后,都會影響到后面的,實(shí)在找不出解決辦法,最后去網(wǎng)上看了這篇解法,豁然開朗,你不要想著打破哪個,而是保留哪個,這應(yīng)該也是這個算法最難的地方了,其他地方參考那篇解法,寫的很贊了。