原题:
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
解:
int maxCoins(vector<int>& nums) {
int left_bound, right_bound, last_die;
int len = nums.size();
int num[len+2];
for(int i=1; i<len+1;i++){
num[i] = nums[i-1];
}
num[0] = 1;
num[len+1]=1;
int part_coin_max[len+2][len+2];
memset(part_coin_max,0,sizeof(int)*(len+2)*(len+2));
for(int width=0; width<=len; width++){
for(int left_bound=1; left_bound+width<=len; left_bound++){
right_bound = left_bound+width;
for(int last_die=left_bound; last_die<=right_bound;last_die++){
part_coin_max[left_bound][right_bound] = max(
part_coin_max[left_bound][right_bound],
part_coin_max[left_bound][last_die-1]
+ num[left_bound-1] * num[last_die] * num[right_bound+1]
+ part_coin_max[last_die+1][right_bound]);
}
}
}
/*for(int i=0;i<len+2;i++){
for(int j=0;j<len+2;j++){
cout << part_coin_max[i][j] << " ";
}
cout << endl;
}*/
return part_coin_max[1][len];
}
len+2:数组的长度,其头尾都是1
num[left_bound]:局部块左边界
num[right_bound]:局部块右边界
num[last_die]:最后死的单元
num[left_bound-1]:最后死的单元左乘单元
num[right_bound+1]:最后死的单元右乘单元
part_coin_max[i][j]);【i,j】局部块的得分最大值
解题思路:
动态规划、分治、回溯思想。我原来不是很懂,网上大神们的代码又很简洁,看了几篇才明白其中道理。问题原本是不能分治的,因为删除顺序会影响结果,所以目标是找到一个能将问题分块的方法。简单地把数组分成两块会导致不同分块有不同的结果。然而如果我们不从头开始规划,而是从结局开始规划,是可以的,因为对于一个局部块,开始和结局某一单元其左右单元是可以确定的。因此我们可以从某一块中选定最后死的单元,然后就可以开始动态规划了。