POJ - 3295 - Tautology = 枚举 + 二叉树遍历

http://poj.org/problem?id=3295

题意:给若干个小写字母表示bool变量,大写字母表示bool运算,求这个表达式的是否为永真表达式。

输入形如:

ApNp
ApNq

也就是前缀表达式。

所以就写个东西遍历它构造一棵树,然后给同名变量枚举赋值,假如没有任何赋值使得树根输出0,则为永真表达式。

考察二叉树的递归遍历。

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<string>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;

char s[1005];
int cur;

struct TreeNode {
    char type;
    vector<int> son;
} t[1005];
int top;

//建树
int build(int u) {
    //cout<<"u="<<u<<endl;
    t[u].son.clear();
    if(islower(s[cur])) {
        t[u].type = s[cur];
        ++cur;
        return u;
    } else if(isupper(s[cur])) {
        t[u].type = s[cur];
        ++cur;
        t[u].son.push_back(build(++top));
        if(t[u].type != 'N')
            t[u].son.push_back(build(++top));
        return u;
    }
}

bool calc(int u, int val) {
    //cout<<"u="<<u<<endl;
    //cout<<"t[u].type="<<t[u].type<<endl;
    if(islower(t[u].type)) {
        //cout<<((val >> (t[u].type - 'p')) & 1)<<endl;
        return (val >> (t[u].type - 'p')) & 1;
    } else {
        bool val1 = calc(t[u].son[0], val);
        if(t[u].type == 'N')
            return !val1;
        else {
            bool val2 = calc(t[u].son[1], val);
            if(t[u].type == 'K')
                return val1 & val2;
            if(t[u].type == 'A')
                return val1 | val2;
            if(t[u].type == 'E')
                return val1 == val2;
            if(t[u].type == 'C') {
                if(val1 == 1 && val2 == 0)
                    return 0;
                else
                    return 1;
            }
            exit(-1);
        }
    }
}

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    while(~scanf("%s", s)) {
        top = cur = 0;
        if(s[0] == '0')
            break;
        build(++top);
        bool all1 = 1;
        for(int i = 0; i < (1 << 5); ++i) {
            if(calc(1, i) == 0) {
                all1 = 0;
                break;
            }
        }
        puts(all1 ? "tautology" : "not");
    }
}

原文地址:https://www.cnblogs.com/Inko/p/11718935.html

时间: 2024-11-07 09:55:11

POJ - 3295 - Tautology = 枚举 + 二叉树遍历的相关文章

[ACM] POJ 3295 Tautology (构造)

Tautology Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9302   Accepted: 3549 Description WFF 'N PROOF is a logic game played with dice. Each die has six faces representing some subset of the possible symbols K, A, N, C, E, p, q, r, s,

poj 3295 Tautology 伪递归

题目链接: http://poj.org/problem?id=3295 题目描述: 给一个字符串,字符串所表示的表达式中p, q, r, s, t表示变量,取值可以为1或0.K, A, N, C, E 分别表示且,或,非,真蕴含,等值.问表达式是不是永真的,如果是输出“tautology”,否则输出“not”. 解题思路: 这里借用到了递归的本质,也就是对栈的模拟,用递归进行压栈,求表达式的值,再加上对变量状态压缩进行枚举. 1 #include <cstdio>//本代码用G++交就ac,

POJ 3295 Tautology (栈模拟)

Tautology Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10096   Accepted: 3847 Description WFF 'N PROOF is a logic game played with dice. Each die has six faces representing some subset of the possible symbols K, A, N, C, E, p, q, r, s

POJ 3295 Tautology(构造法)

题目网址:http://poj.org/problem?id=3295 题目: Tautology Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13231   Accepted: 5050 Description WFF 'N PROOF is a logic game played with dice. Each die has six faces representing some subset of the po

poj 3295 Tautology

这题属于构造题,有两点需要想到: 1.所谓永真式就是说题设中所给的五个逻辑变量无论如何取值,最终的运算结果总是为真,这里就需要枚举五个逻辑变量的取值情形.很容易想到共有32种情况: 也就是说,对于每个字符串,如果这32种情况下的运算结果都是真的话, 那它就是永真式.1~32, 用按位与的办法,可以逐次枚举这32中情况. 2.运算顺序:可以这样理解题目中的字符串结构,它就像一颗树,所以叶子节点做逻辑运算之后逐次汇聚到根节点得到最后的结果.于是想到从尾部开始(也就是从叶节点向上). 如果遇到逻辑变量

poj 3295 Tautology [ 栈 ]

传送门 Tautology Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10107   Accepted: 3850 Description WFF 'N PROOF is a logic game played with dice. Each die has six faces representing some subset of the possible symbols K, A, N, C, E, p, q,

POJ - 3295 - Tautology (构造)

题目传送:Tautology 思路:枚举所有变量可能的值(0或1),算出其表达式的值,因为题目是要求是否是永真式,求式子的真值可以用栈来求,栈的话,可以自己构造一个栈,也可以用STL的stack AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #in

POJ - 2255 - Tree Recovery = 二叉树遍历

http://poj.org/problem?id=2255 题意:给定先序遍历和中序遍历,求后序遍历. 回忆以前上DataStructure课的时候貌似写过类似的. 先从先序入手,从左到右扫描,进入时节点时立刻入栈,离开节点时立刻出栈. 关键是怎么知道什么时候才是立刻节点了呢? 貌似只有n^2的做法,因为要从中序遍历序列中找根. 但其实假如预处理出中序遍历的序列中的字母每个指向的位置就不用这额外的时间花费n了. 也就是从先序遍历入手,进入节点时把根节点的中序遍历序列指针两侧递归下去. 所以构造

POJ 2255 Tree Recovery 二叉树恢复

一道和Leetcode的一道题目基本上一样的题目. 给出前序遍历和中序遍历序列,要求根据这些信息恢复一颗二叉树的原貌,然后按后序遍历序列输出. Leetcode上有给出后序和中序,恢复二叉树的. 不过其实算法都是一样的.仿佛又回到了做Leetcode题的那段岁月中了. 还有就是输入是我特别处理过的,就两个函数,大家会了的无视,不会的可以学习下. #include <stdio.h> #include <string> #include <algorithm> using