洛谷 P1310 表达式的值
前言
表达式树万岁!
如您所见,这题要构造表达式树。(但是我 T 了一个点)
正文
表达式树
*
|-+
|-|-5
|-|-7
|-12
这棵树的值为 144,看懂了吗?(这里*+
不是题目里的*+
)
另外有一点,这个表达式树得是个二叉树。(别问我为什么)
构造表达式树
我们的函数就叫做 $ parse(l, r) $ 吧,初始时调用 $ parse(0, L) $。
当 $ l = r $ 时,直接返回一个未知数节点即可。
否则找优先级最低的运算,其中括号整个跳过。
比如在 *(++)+
里,找到第 6 个字符,也就是下标 5 的字符,创建一个节点。
这个节点的左孩子设为 $ parse(0, 5) $ ,右孩子设为 $ parse(6, 6) $。
最后返回这个节点即可。
DFS
全称:dynamic first search。(确信)
中文:记忆化搜索。(还好不至于离大谱)
- 如果要让值为0,那么:
- 是
+
:- 左边 0,右边 0。
- 是
*
:- 左边 0,右边 0。
- 左边 0,右边 1。
- 左边 1,右边 0。
- 是
- 如果要让值为1,那么:
- 是
+
:- 左边 0,右边 1。
- 左边 1,右边 0。
- 左边 1,右边 1。
- 是
*
:- 左边 1,右边 1。
- 是
这题就很好写了。
注意加 DP,模 10007。
#include <bits/stdc++.h>
using namespace std;
/***************************/
struct node {
char type; // _ + *
int lc, rc;
node(char tp = '_', int l = -1, int r = -1) {
type = tp;
lc = l;
rc = r;
}
} node[1000005];
int node_cnt = 0;
int create(char tp, int l, int r) {
node[node_cnt].type = tp;
node[node_cnt].lc = l;
node[node_cnt].rc = r;
return node_cnt++;
}
/***************************/
int N;
string s;
int parse(int l, int r, int dbg = 0) {
// for (int i = 0; i < dbg; i++) {
// putchar('|');
// putchar('-');
// }
// printf("parse(%d, %d)\n", l, r);
if (l == r) {
return create('_', -1, -1);
}
for (int i = l; i < r; i++) {
if (s[i] == '(') {
int lb = 1;
i++;
while (lb) {
if (s[i] == '(') {
lb++;
} else if (s[i] == ')') {
lb--;
}
i++;
}
i--;
} else if (s[i] == '+') {
return create('+', parse(l, i, dbg + 1), parse(i + 1, r, dbg + 1));
}
}
for (int i = l; i < r; i++) {
if (s[i] == '(') {
int lb = 1;
i++;
while (lb) {
if (s[i] == '(') {
lb++;
} else if (s[i] == ')') {
lb--;
}
i++;
}
i--;
} else if (s[i] == '*') {
return create('*', parse(l, i, dbg + 1), parse(i + 1, r, dbg + 1));
}
}
return parse(l + 1, r - 1, dbg + 1);
}
/***************************/
int f[1000005][2];
int dynamic_first_search(int x, int res) {
if (f[x][res]) return f[x][res];
else if (node[x].type == '_') return f[x][res] = 1;
else {
if (node[x].type == '+') {
if (res == 0) {
return f[x][res]
= (dynamic_first_search(node[x].lc, 0) * dynamic_first_search(node[x].rc, 0))
% 10007;
} else {
return f[x][res]
= (dynamic_first_search(node[x].lc, 0) * dynamic_first_search(node[x].rc, 1)
+ dynamic_first_search(node[x].lc, 1) * dynamic_first_search(node[x].rc, 0)
+ dynamic_first_search(node[x].lc, 1) * dynamic_first_search(node[x].rc, 1))
% 10007;
}
} else {
if (res == 1) {
return f[x][res]
= (dynamic_first_search(node[x].lc, 1) * dynamic_first_search(node[x].rc, 1))
% 10007;
} else {
return f[x][res]
= (dynamic_first_search(node[x].lc, 1) * dynamic_first_search(node[x].rc, 0)
+ dynamic_first_search(node[x].lc, 0) * dynamic_first_search(node[x].rc, 1)
+ dynamic_first_search(node[x].lc, 0) * dynamic_first_search(node[x].rc, 0))
% 10007;
}
}
}
}
/***************************/
int main() {
cin >> N;
cin >> s;
parse(0, N);
// for (int i = 0; i < node_cnt; i++) {
// printf("%c %d %d\n", node[i].type, node[i].lc, node[i].rc);
// }
cout << dynamic_first_search(node_cnt - 1, 0);
return 0;
}
后续
今日待办:
能不能把最后一项达成啊各位!!!