poj.org/problem?id=3383
这题不难,但是AC比例也很低
Total Submissions: 101 | Accepted: 14 | Special Judge |
大致题意是:
1. 定义4个集合操作,有不同的优先级,给定一个方程,和已知的一些变量的值 (每个变量都是一个集合),包括全集,判断方程中的未知变量是否有解
思路
集合变量是否有解比较简单,只要判断对于全集中的任一个元素,如何这个方程左边和右边的计算结果可以同时包含这个元素,或是同时不包含这个元素,那么这个元素就可以满足方程;如果某个元素的取舍无法满足方程,则说明方程无界;
对于未知变量的解也很简单,对已任意元素,如果不包含这个元素就可以满足方程,那么就可以按照左右两边的计算结果都不包含该元素来贪心赋值即可
所以问题就归结为
1. 解析方程字符串为二元运算表达式数
2. 对于任意元素, 依次dfs检查以当前节点为根的表达式数是否可以包含/不包含这个元素,如果某个节点既不能包含也不能不包含某个元素,这该表达式树无效
3. 对于有效的表达式树,再次dfs设置那些未知变量是否包含这个元素
实现
代码量比较大,感觉这题主要是代码能力,如何解析表达式应该算是基本功吧 (去年写了一个基于公式的k8s HPA扩展controller,写起来还是比较轻松的)
对于又优先级的表达式,只需要维护一个优先级递增的栈即可, 这里只有四种操作,所以栈的最大长度是4
int parse(char *p, int *pi) {
int i =*pi, j, k;
char op[8], oc=0, co, cr, oo, or, bbb;
int nn[8], nc=0, n1, n2, n;
while(1) {
while(p[i]&&(p[i]==' '||p[i]=='\t')) i++; if (p[i]==0) break;
if (p[i]==')') break;
if (p[i]=='(') {
i++; n=parse(p, &i); if (p[i]!=')') assert(0); i++;
nn[nc++]=n;