一.大气球的最大得分

1.对应letecode链接

打气球的最大分数_牛客题霸_牛客网 (nowcoder.com)

2.题目描述:

3.解题思路

本题个人觉得本题巨难:主要步骤如下:

1.预处理:为便于处理,可在 nums 数组两端各添加一个哨兵 1,即nums[0]=和nums[N]=1,其中N为数组的长度。

2.定义递归函数func(vector<int>&nums,int L,int R)其递归含义为nums[L........R]范围内能获得的最大得分

3.我们发现我们在尝试可能性时对应每个位置的得分和它左边的状态和右边的状态都有关这使得尝试的可能性非常的多所以。我们可以这样尝试,我们尝试每个废物最后打爆能获得的最大得分。

4.注意:递归函数func必须保证一个潜台词nums[L-1]位置的数必须没爆并且nums[R+1]位置的数也没爆必须遵守否则就别调这个函数

首先在一头一尾添加一个1,这个是为了方便代码实现。下面我们可以产生可能性

我们尝试cur位置最后被打爆注意:(如果一个区间为(left,right)那么这个区间里面一个气球也没有)。我们每个位置都这样尝试最后答案一定就在其中我们只需要进行更新即可。

4.对应代码:

#include<iostream>
#include<vector>
using namespace std;
//潜台次arr[L-1]位置和arr[R+1]位置一定没爆
//递归含义arr[L.....R]范围内的最大得分
int func(vector<int>& arr, int L, int R) {if (L == R) { //只有一个气球打爆即可return arr[L] * arr[L - 1] * arr[R + 1];}//可能性1:最后打爆arr[L]位置的气球int p1 = func(arr, L + 1, R) + arr[L] * arr[L - 1] * arr[R + 1];//可能性2:最后打爆arr[R]位置的气球int p2 = func(arr, L, R - 1) + arr[R] * arr[L - 1] * arr[R + 1];int ans = max(p1, p2);for (int i = L + 1; i < R; i++) {//产生[L+1,R-1]范围内每个位置最后打爆能获得的最大得分int left = func(arr, L, i - 1); //打爆左边部分int right = func(arr, i + 1, R); //打爆右边部分int cur = arr[i] * arr[L - 1] * arr[R + 1]; //打爆当前位置ans = max(ans, cur + left + right);//更新答案}return ans;
}
int maxCoins(vector<int>& nums) {int N = nums.size();vector<int>arr(N + 2);for (int i = 0; i < N; i++) {arr[i + 1] = nums[i];}arr[0] = arr[N + 1] = 1;dp.resize(N + 1, vector<int>(N + 1, -1));return func(arr, 1, N);
}int main() {int N;cin >> N;vector<int>arr(N);for (int i = 0; i < N; i++) {cin >> arr[i];}cout << maxCoins(arr) << endl;return 0;
}

2.记忆化搜索代码:

#include<iostream>
#include<vector>
using namespace std;
vector<vector<int>>dp;
//潜台次arr[L-1]位置和arr[R+1]位置一定没爆
//递归含义arr[L.....R]范围内的最大得分
int func(vector<int>& arr, int L, int R) {if (L == R) { //只有一个气球打爆即可return arr[L] * arr[L - 1] * arr[R + 1];}if (dp[L][R] != -1) {return dp[L][R];}//可能性1:最后打爆arr[L]位置的气球int p1 = func(arr, L + 1, R) + arr[L] * arr[L - 1] * arr[R + 1];//可能性2:最后打爆arr[R]位置的气球int p2 = func(arr, L, R - 1) + arr[R] * arr[L - 1] * arr[R + 1];int ans = max(p1, p2);for (int i = L + 1; i < R;i++) {//产生[L+1,R-1]范围内每个位置最后打爆能获得的最大得分int left = func(arr, L, i - 1); //打爆左边部分int right = func(arr, i + 1, R); //打爆右边部分int cur = arr[i] * arr[L - 1] * arr[R + 1]; //打爆当前位置ans = max(ans, cur + left + right);//更新答案}dp[L][R] = ans;return ans;
}
int maxCoins(vector<int>& nums) {if (nums.size() == 0) {return 0;}int N = nums.size();vector<int>arr(N + 2);for (int i = 0; i < N; i++) {arr[i + 1] = nums[i];}arr[0] = arr[N + 1] = 1;dp.resize(N + 1, vector<int>(N + 1, -1));return func(arr, 1, N);
}int main() {int N;cin >> N;vector<int>arr(N);for (int i = 0; i < N; i++) {cin >> arr[i];}dp.resize(N + 1, vector<int>(N + 1, -1));cout << maxCoins(arr) << endl;return 0;
}

严格位置依赖的动态规划:

#include<iostream>
#include<vector>
using namespace std;int maxCoins(vector<int>& nums) {if (nums.size() == 0) {return 0;}int N = nums.size();vector<int>arr(N + 2);for (int i = 0; i < N; i++) {arr[i + 1] = nums[i];}arr[0] = arr[N + 1] = 1;vector<vector<int>>dp(N + 2, vector<int>(N + 2));for (int i = 1; i <= N; i++) {dp[i][i] = arr[i] * arr[i - 1] * arr[i + 1];}for (int L = N; L >= 1; L--) {for (int R = L + 1; R <= N; R++) {int ans = max(arr[L - 1] * arr[L] * arr[R + 1] + dp[L + 1][R],arr[L - 1] * arr[R] * arr[R + 1] + dp[L][R - 1]);for (int i = L + 1; i < R; i++) {int left = dp[L][i - 1];int right = dp[i + 1][R];int cur = arr[i] * arr[L - 1] * arr[R + 1];ans = max(ans, left + right + cur);}dp[L][R] = ans;}}return dp[1][N];}int main() {int N;cin >> N;vector<int>arr(N);for (int i = 0; i < N; i++) {cin >> arr[i];}cout << maxCoins(arr) << endl;return 0;
}

二.布尔运算

1.对应letecode链接

面试题 08.14. 布尔运算 - 力扣(LeetCode)

2.题目描述:

3.解题思路:

1.尝试每个符号最后进行计算能够得到的true或者false的方法数。

2.定义递归函数Info*func(str,L,R)的含义为str从[L......R]范围内为true和false的方法数。并且L和R位置非0就是1,具体请看代码

4.对应代码

class Solution {public:struct Info {Info(int tr, int tf) {t = tr;f = tf;}int t;//t代表为true的方法数int f;//代表为false的方法数};int countEval(string s, int result) {dp.resize(s.size(), vector<Info*>(s.size(), NULL));Info* ret = func(s, 0, s.size() - 1);return result == 1 ? ret->t : ret->f;}//L......R上必须L和R非0就是1Info* func(const string& str, int L, int R) {int t = 0;int f = 0;if (L == R) {t = str[L] == '1' ? 1 : 0;f = str[L] == '0' ? 1 : 0;}else {//注意一定要保存递归的潜台词L和R位置非0即1for (int Split = L + 1; Split < R;Split += 2) { //尝试每个符号最后进行运算能够得到结果的方法数Info* leftInfo = func(str, L, Split - 1);Info* rightInfo = func(str, Split + 1, R);int a = leftInfo->t;int b = leftInfo->f;int c = rightInfo->t;int d = rightInfo->f;switch (str[Split]) { //根据最后算的这个符号进行分类计算case'&':t += a * c;f += b * c + b * d + a * d;break;case'|':t += a * c + a * d + b * c;f += b * d;break;case '^':t += a * d + b * c;f += a * c + b * d;break;}}}Info* ans = new Info(t, f);return ans;}};

记忆化搜索:

class Solution {public:struct Info {Info(int tr, int tf) {t = tr;f = tf;}int t;int f;};vector<vector<Info*>>dp;int countEval(string s, int result) {dp.resize(s.size(), vector<Info*>(s.size(), NULL));Info* ret = func(s, 0, s.size() - 1);return result == 1 ? ret->t : ret->f;}//L......R上必须L和R非0就是1Info* func(const string& str, int L, int R) {if (dp[L][R]) {return dp[L][R];}int t = 0;int f = 0;if (L == R) {t = str[L] == '1' ? 1 : 0;f = str[L] == '0' ? 1 : 0;}else {cout << L << " " << R << endl;for (int Split = L + 1; Split < R; Split += 2) {Info* leftInfo = func(str, L, Split - 1);Info* rightInfo = func(str, Split + 1, R);int a = leftInfo->t;int b = leftInfo->f;int c = rightInfo->t;int d = rightInfo->f;switch (str[Split]) {case'&':t += a * c;f += b * c + b * d + a * d;break;case'|':t += a * c + a * d + b * c;f += b * d;break;case '^':t += a * d + b * c;f += a * c + b * d;break;}}}Info* ans = new Info(t, f);dp[L][R] = ans;return ans;}};

戳气球和布尔运算问题(巨难)相关推荐

  1. 312. Burst Balloons 戳气球

    Title 有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中. 现在要求你戳破所有的气球.如果你戳破气球 i ,就可以获得 nums[left] * nu ...

  2. LeetCode312 戳气球

    回溯思想 很显然涉及求最值,没有任何奇技淫巧,一定是穷举所有可能的结果,然后对比得出最值 所以说,只要遇到求最值的问题,首先要思考的就是:如何穷举所有可能的结果 穷举主要有两种算法:就是回溯算法和动态 ...

  3. Leetcode 312. 戳气球

    题目 首先必须要说明,这个题目的状态转移方程真的比较巧妙,所以说如果你看了题目之后完全没有思路恰恰是正常的.虽然最优答案不容易想出来,但基本的思路分析是我们应该力求做到的.所以本文会先分析一下常规思路 ...

  4. LeetCode·312.戳气球·动态规划

    312.戳气球 题目 示例 思路 首先必须要说明,这个题目的状态转移方程真的比较巧妙,所以说如果你看了题目之后完全没有思路恰恰是正常的.虽然最优答案不容易想出来,但基本的思路分析是我们应该力求做到的. ...

  5. 经典动态规划:戳气球问题

    点击上方蓝字设为星标 东哥带你手把手撕力扣~ 作者:labuladong   公众号:labuladong 若已授权白名单也必须保留以上来源信息 今天我们要聊的这道题「Burst Balloon」和之 ...

  6. LeetCode312:戳气球

    要求 有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中. 现在要求你戳破所有的气球.戳破第 i 个气球,你可以获得 nums[i - 1] * num ...

  7. gdut-与蓝神一起戳气球 hnust-硬币翻转 - 博弈论

    与蓝神一起戳气球 题目描述 As you know,13-14!=-1.(^@^) 但是蓝神偏不信.所以,现在问题来了.你要与蓝神通过我们最喜欢的游戏--戳气球一决胜负. 现有n个气球,你和蓝神轮流戳 ...

  8. Leetcode.312 戳气球

    题目链接 Leetcode.312 戳气球 题目描述 有 n个气球,编号为0到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums中. 现在要求你戳破所有的气球.戳破第 i 个气球,你可 ...

  9. 【LeetCode】312. 戳气球

    312. 戳气球(困难) 解法一:动态规划 首先看一个区间: 区间(i,j) 是一个开区间,因为我们只能戳爆 i 和 j 之间的气球,不能戳爆索引为 i 和 j 的气球. 我们不妨考虑该区间内被戳爆的 ...

最新文章

  1. fiash星空动画制作_三维动画制作的详细流程
  2. React实践debug:JSX输出的限制(存疑)
  3. 笔记-信息化与系统集成技术-供应链的特征
  4. JDBC连接时所犯错误1.字符集设置不合适2.连接MySQL8.0社区版时时区不一致3..包名不能以Java.命名4.驱动被弃用
  5. SpringCloud Greenwich(四)注册中心之eureka、Zuul和 gateway网关配置
  6. 【kotin】统计字符串中的字母数(拓展函数)
  7. 03-18 OpenSTF-手机设备管理平台
  8. java第七章jdbc课后简答题_jsp编程基础第七章习题
  9. 基于Mat变换的骨架提取Java
  10. DiskCatalogMaker for Mac(磁盘管理工具)
  11. c++ 调用com组件步骤
  12. 标准c语言教程gary,C语言标准教程
  13. 腾讯云老用户重新注册新账号算新用户吗?
  14. 如何关闭计算机英语作文,英语作文lt;关掉你的电脑gt;
  15. Linux Shell 并行
  16. 错误: Unknown class XXX in Interface Builder file
  17. Java笔记——数据库05
  18. C#实现万年历(农历、节气、节日、星座、属相、生肖、闰年等)
  19. CISP-PTE维持记录(2022-03-30)
  20. 系统定位的问题,优化的简述

热门文章

  1. xgboost和lightgbm算法总结(从决策树到xgboost)
  2. Ubuntu 添加用户到sudoers
  3. java中判断复选框是否选中_php 判断复选框checkbox是否被选中
  4. 有机玻璃与普通玻璃特性对比
  5. idea中查看git的分支版本
  6. C语言利用循环队列实现滑动平均值滤波器,提高计算速度
  7. uniapp实现和webview中的H5进行通讯,返回跳出webview页面到app页面中
  8. 1023: 东北串王数签子
  9. 数澜科技荣获2020铅笔道·真榜「中国最具投资价值创新企业TOP200」
  10. Nginx学习(一)——Nginx基础知识