戳气球和布尔运算问题(巨难)

article/2025/9/10 15:52:30

一.大气球的最大得分

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;}};


http://chatgpt.dhexx.cn/article/RwMXov5o.shtml

相关文章

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

点击上方蓝字设为星标 东哥带你手把手撕力扣~ 作者&#xff1a;labuladong 公众号&#xff1a;labuladong若已授权白名单也必须保留以上来源信息 今天我们要聊的这道题「Burst Balloon」和之前我们写过的那篇 经典动态规划&#xff1a;高楼扔鸡蛋问题 分析过的高楼扔鸡蛋问题类…

*312戳气球

​​​​​​戳气球 有 n 个气球&#xff0c;编号为0 到 n - 1&#xff0c;每个气球上都标有一个数字&#xff0c;这些数字存在数组 nums 中。 现在要求你戳破所有的气球。戳破第 i 个气球&#xff0c;你可以获得 nums[i - 1] * nums[i] * nums[i 1] 枚硬币。 这里的 i - 1 …

力扣---戳气球

力扣—戳气球 文章目录 力扣---戳气球一、题目描述二、回溯思路三、动态规划思路四、代码 一、题目描述 有 n 个气球&#xff0c;编号为0 到 n-1&#xff0c;每个气球上都标有一个数字&#xff0c;这些数字存在数组 nums 中。 现在要求你戳破所有的气球。每当你戳破一个气球 …

【LeetCode】312. 戳气球

312. 戳气球&#xff08;困难&#xff09; 解法一&#xff1a;动态规划 首先看一个区间&#xff1a; 区间(i,j) 是一个开区间&#xff0c;因为我们只能戳爆 i 和 j 之间的气球&#xff0c;不能戳爆索引为 i 和 j 的气球。 我们不妨考虑该区间内被戳爆的最后一个气球&#xff…

LeetCode312:戳气球

要求 有 n 个气球&#xff0c;编号为0 到 n - 1&#xff0c;每个气球上都标有一个数字&#xff0c;这些数字存在数组 nums 中。 现在要求你戳破所有的气球。戳破第 i 个气球&#xff0c;你可以获得 nums[i - 1] * nums[i] * nums[i 1] 枚硬币。 这里的 i - 1 和 i 1 代表和…

【动态规划】LeetCode 312. 戳气球 --区间DP问题

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…

Golang每日一练(leetDay0105) 最小高度树、戳气球

目录 310. 最小高度树 Minimum Height Trees &#x1f31f;&#x1f31f; 312. 戳气球 Burst Balloons &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一…

Leetcode.312 戳气球

题目链接 Leetcode.312 戳气球 题目描述 有 n个气球&#xff0c;编号为0到 n - 1&#xff0c;每个气球上都标有一个数字&#xff0c;这些数字存在数组 nums中。 现在要求你戳破所有的气球。戳破第 i 个气球&#xff0c;你可以获得 n u m s [ i − 1 ] ∗ n u m s [ i ] ∗ …

LeetCode 312. 戳气球(Java)

题目 有 n 个气球&#xff0c;编号为0 到 n - 1&#xff0c;每个气球上都标有一个数字&#xff0c;这些数字存在数组 nums 中。 现在要求你戳破所有的气球。戳破第 i 个气球&#xff0c;你可以获得 nums[i - 1] * nums[i] * nums[i 1] 枚硬币。 这里的 i - 1 和 i 1 代表和…

每日一道算法题(3)--戳气球问题

题目 戳气球问题 :输入一个包含非负数整数的数组nums代表一排气球, nums[i]代表第i个气球的分数。现在, 你要戳破所有的气球,请计算出最高的分数。 分数的计算规则比较特别&#xff0c;当戳破第i个气球时, 可以获得nums[left] * nums[right] * nums[i]的分数&#xff0c;其中nu…

【leetcode】312.戳气球 (超详细解析,动态规划)

312. 戳气球 难度困难 有 n 个气球&#xff0c;编号为0 到 n-1&#xff0c;每个气球上都标有一个数字&#xff0c;这些数字存在数组 nums 中。 现在要求你戳破所有的气球。如果你戳破气球 i &#xff0c;就可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 lef…

戳气球问题

戳气球问题本质上可以认为是一种组合逆推的问题&#xff08;背包问题模型&#xff09; 我们可以有两种方法 1.dfs爆搜法 2.dp法 1.dfs爆搜法 dfs爆搜就是暴力枚举出哪个先破&#xff0c;哪个后破&#xff0c;直到找出最佳的方案 本质上是一个全排列问题&#xff0c;但是全…

Linux修改主机名—主机名和IP映射

一、修改主机名 /etc/sysconfig/network 二、主机名和IP映射 /etc/hosts Windows 里面的路径&#xff1a;C:\Windows\System32\drivers\etc

Linux系统下如何修改主机名

Linux系统安装好后&#xff0c;都会有默认的主机名&#xff0c;这里以CentOS系统为例&#xff0c;默认的主机名为localhost.localdomain&#xff0c;为了便于使用&#xff0c;我们常常需要修改主机名&#xff0c;下面演示的是永久更改主机名的方法。 方法/步骤 以根用户登录&a…

杂记 | Linux修改主机名(不用重启)

新买的云服务器主机名比较奇怪。强迫症难受&#xff0c;于是想通过Linux命令修改主机名&#xff0c;且选择最轻松的方案&#xff08;不想重启系统&#xff09;&#xff0c;使用以下命令即可&#xff1a; hostnamectl set-hostname 主机名 systemctl restart systemd-hostnamed…

修改Linux的主机名

修改主机名 新申请下来的设备&#xff0c;修改root后面的主机名为一连串的字符和数字用于centos7.X&#xff0c;其他版本未验证 修改主机名 hostnamectl set-hostname Test_Server1修改后可查看是否修改成功 cat /etc/hostname也可以通过修改hostname文件修改主机名未生效可…

Linux 永久修改主机名(转载)

Linux修改主机名&#xff0c;永久生效。 linux查看主机名: 查看主机命令&#xff1a; [rootlinux_epm2 ~]# hostname localhost.localdomain localhost.localdomain即为默认的主机名。 修改network文件: 用root用户登录&#xff0c;如果不是root用户&#xff0c;使用su命令切换…

Linux修改主机名(hostname)

查看当前的主机名 #第一种hostname #第二种hostnamectl修改主机名 执行修改命令&#xff1a; hostnamectl set-hostname <new-hostname>编辑hosts文件 vim /etc/hosts

Linux修改主机名(静态主机名、临时主机名)

背景 通常情况下Linux在安装时会设置主机名、root密码等相关参数&#xff0c;但安装后的使用过程中或许你需要修改主机名&#xff0c;本文讲述如何修改主机名&#xff0c;包括临时修改和永久修改。 查看主机名 原生态的Linux一般自带两个命令&#xff1a;hostname、hostname…

linux修改主机名命令

一、 使用hostname命令 比如我现在的主机名是haozhikuan-hbza&#xff0c;如果我想把主机名变成hbza-hbza可以用 hostname hbza-hbza 然后 hostname 或者uname -u都可以查看自己的主机名&#xff0c;如果再新打开一个终端就能看到自己的主机名已经修改过变成hbza-hbza了。 不…