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

后续

今日待办:

能不能把最后一项达成啊各位!!!

posted @ 2022-08-04 22:05  A-Problem-Solver  阅读(38)  评论(0编辑  收藏  举报