(给算法爱好者加星标,修炼编程内功)
来源:labuladong
今天我们要聊的这道题「Burst Balloon」和之前我们写过的那篇经典动态规划:高楼扔鸡蛋问题分析过的高楼扔鸡蛋问题类似,知名度很高,但难度确实也很大。因此作者就给这道题赐个座,来看一看这道题目到底有多难。
它是 LeetCode 第 312 题,题目如下:
首先必须要说明,这个题目的状态转移方程真的比较巧妙,所以说如果你看了题目之后完全没有思路恰恰是正常的。虽然最优答案不容易想出来,但基本的思路分析是我们应该力求做到的。所以本文会先分析一下常规思路,然后再引入动态规划解法。
一、回溯思路
先来顺一下解决这种问题的套路:
我们前文多次强调过,很显然只要涉及求最值,没有任何奇技淫巧,一定是穷举所有可能的结果,然后对比得出最值。
所以说,只要遇到求最值的算法问题,首先要思考的就是:如何穷举出所有可能的结果?
穷举主要有两种算法,就是回溯算法和动态规划,前者就是暴力穷举,而后者是根据状态转移方程推导「状态」。
如何将我们的扎气球问题转化成回溯算法呢?这个应该不难想到的,我们其实就是想穷举戳气球的顺序,不同的戳气球顺序可能得到不同的分数,我们需要把所有可能的分数中最高的那个找出来,对吧。
那么,这不就是一个「全排列」问题嘛,我们前文 回溯算法框架套路详解 中有全排列算法的详解和代码,其实只要稍微改一下逻辑即可,伪码思路如下:
int res = Integer.MIN_VALUE;
/* 输入一组气球,返回戳破它们获得的最大分数 */
int maxCoins(int[] nums) {
backtrack(nums, 0);
return res;
}
/* 回溯算法的伪码解法 */
void backtrack(int[] nums, int socre) {
if (nums 为空) {
res = max(res, score);
return;
}
for (int i = 0; i int point = nums[i-1] * nums[i] * nums[i+1]; int temp = nums[i]; // 做选择 在 nums 中删除元素 nums[i] // 递归回溯 backtrack(nums, score + point); // 撤销选择 将 temp 还原到 nums[i] }}
回溯算法就是这么简单粗暴&#