不讲
T3: 逻辑表达式
分做法: 的时候能满足的字符串很少只有 a|b
,a&b
, a
,b
四种。 的时候再加上a|b|c
,a|b&c
,a&b|c
,a&b&c
这四种,把八种情况分别计算就能拿到 分。
分做法:考虑 的情况,我们可以建出表达式树,递归求解答案
分做法:对于特殊性质 ,我们可以从左往右处理,看这样一个例子 0|(1|0)|(0|(1|0))
, 遇到左括号:如果 |
的左边是 就直接跳到对应右括号,如果 |
的左边是 就递归到下一层
分做法:本题是一道模拟题,含括号的表达式求值,一般可以使用递归或栈模拟。
中缀表达式转后缀表达式
代码实现
#include <bits/extc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; struct Node { int v, cOr, cAnd; Node() {} Node(int v=0, int cOr=0, int cAnd=0): v(v), cOr(cOr), cAnd(cAnd) {} }; int getPriority(char op) { if (op == '(') return 0; if (op == '|') return 1; return 2; } string inToPost(string s) { stack<char> stk; string res; for (int c : s) { if (c == '(') stk.push('('); else if (c == ')') { while (stk.top() != '(') { res += stk.top(); stk.pop(); } stk.pop(); } else if (c == '&' or c == '|') { while (stk.size() and getPriority(c) <= getPriority(stk.top())) { res += stk.top(); stk.pop(); } stk.push(c); } else res += c; } while (stk.size()) { res += stk.top(); stk.pop(); } return res; } int main() { string s; cin >> s; string t = inToPost(s); stack<Node> stk; for (char c : t) { if (c == '|') { auto [v1, cOr1, cAnd1] = stk.top(); stk.pop(); auto [v2, cOr2, cAnd2] = stk.top(); stk.pop(); stk.emplace(v2|v1, cOr2+(v2==1?1:cOr1), cAnd2+(v2==1?0:cAnd1)); } else if (c == '&') { auto [v1, cOr1, cAnd1] = stk.top(); stk.pop(); auto [v2, cOr2, cAnd2] = stk.top(); stk.pop(); stk.emplace(v2&v1, cOr2+(v2==0?0:cOr1), cAnd2+(v2==0?1:cAnd1)); } else stk.emplace(c-'0', 0, 0); } auto [v, cOr, cAnd] = stk.top(); cout << v << '\n'; cout << cAnd << ' ' << cOr << '\n'; return 0; }
T4:上升点列
分做法: 时,可用类似最长上升子序列的做法处理
分做法:当 和 比较小的时候,我们可以把它当成一个棋盘 ,如果这个坐标有对应的点那么代价为 ,否则代价为 ,任意点都能作为起点,枚举终点,求出代价小于 的时候到达终点的最长路。可以通过 和 的测试点。
分做法:再考虑 的情况,只能连续选择,把每个点按照横坐标排序,然后枚举每个点 , 只能接在坐标小于 且曼哈顿距离为 的点 后面,。可以通过 的测试点。
分做法:考虑到添加的 个点是自由的,我们可以用这 个点来填补曼哈顿距离大于 的相邻点,如果两个点之间没有相邻点,并且它们的曼哈顿距离是 ,那么需要填充 个点,才能把这两个点同时选出来。整个序列最多填充 个点。
我们可以把填充的点数当做选择相邻两个点的代价,那么这道题就转化成在 个点选出总代价不超过 的序列,要求序列最长,就变成一个子序列问题了。
子序列的另一个要求是横坐标、纵坐标均单调不减,我们把 个点按 坐标排序,枚举当前点之前的所有点,再判断 坐标是否小于等于当前点即可。
使用动态规划求解子序列问题,记 dp[i][j]
表示在排序后的前 个点中,选出代价为 的子序列,能得到的序列的最长长度。
转移方程:
其中 的取值范围是 , 是 点与 点的曼哈顿距离。
需要注意,最后 个点一定全部都会用上,如果求出序列没有用上所有的 个点,那么可以把剩下的 个点直接加在最后一个点后面。
时间复杂度:
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) #define x first #define y second using namespace std; using P = pair<int, int>; int dp[505][105]; inline void chmax(int& x, int y) { if (x < y) x = y; } int main() { int n, k; cin >> n >> k; vector<P> ps(n); rep(i, n) cin >> ps[i].x >> ps[i].y; sort(ps.begin(), ps.end()); int ans = 0; rep(i, n) { rep(j, k+1) { dp[i][j] = j+1; rep(t, i) if (ps[t].y <= ps[i].y) { int d = (ps[i].x-ps[t].x) + (ps[i].y-ps[t].y); int nj = j-d+1; if (nj >= 0) chmax(dp[i][j], dp[t][nj]+d); } } chmax(ans, dp[i][k]); } cout << ans << '\n'; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!