CSP-J2020 T3 表达式 + CSP-J2022 T3 逻辑表达式

 CSP-J 2020 T3 表达式


题目传送门

我们来看题面:

1.给后缀表达式

2.多次询问,应该需要打表

**************************************************************************************************************

后缀表达式:

1.栈(会超时)

2.建表达式树(二叉树通常拿来优化)

**************************************************************************************************************

有了二叉树,我们就会想到DFS

那具体如何DFS呢?

我们可以这样:

1.用DFS求原表达式

2.新建DFS函数来看这里的点改变后,是否会影响表达式的值

*************************************************************************************************************

所以便有了整体思路:

1.建表达式树

2.DFS记表

3.读入询问,看是否会改变

**************************************************************************************************************

整体代码:

#include <bits/stdc++.h>
using namespace std;
#define N 400005
string str;
int n, q, cnt;
vector<int> tree[N];
char o[N];
int v[N];
stack<int> stk;
bool flag[N];
int dfs1(int root)
{
    if(root <= n) return v[root];
    if(o[root] == '&') return v[root] = dfs1(tree[root][0]) & dfs1(tree[root][1]);
    if(o[root] == '|') return v[root] = dfs1(tree[root][0]) | dfs1(tree[root][1]);
    if(o[root] == '!') return v[root] = !dfs1(tree[root][0]);
}
void dfs2(int root)
{
    flag[root] = true;
    if(o[root] == '&')
    {
        if(v[tree[root][0]] == 1) dfs2(tree[root][1]);
        if(v[tree[root][1]] == 1) dfs2(tree[root][0]);
    }
    if(o[root] == '|')
    {
        if(v[tree[root][0]] == 0) dfs2(tree[root][1]);
        if(v[tree[root][1]] == 0) dfs2(tree[root][0]);
    }
    if(o[root] == '!') dfs2(tree[root][0]);
}
int main()
{
    getline(cin, str);
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> v[i];
    cnt = n + 5;
    for(int i = 0; i < str.length(); i++)
    {
        if(str[i] == 'x')
        {
            int num = 0;
            int j = i + 1;
            while(str[j] >= '0' && str[j] <= '9')
            {
                num = num * 10 + str[j] - '0';
                j++;
            }
            stk.push(num);
        }
        else if(str[i] == '&' || str[i] == '|')
        {
            int a = stk.top(); stk.pop();
            int b = stk.top(); stk.pop();
            stk.push(++cnt);
            tree[cnt].push_back(a);
            tree[cnt].push_back(b);
            o[cnt] = str[i];
        }
        else if(str[i] == '!')
        {
            int a = stk.top(); stk.pop();
            stk.push(++cnt);
            tree[cnt].push_back(a);
            o[cnt] = '!';
        }
    }
    int res = dfs1(stk.top());
    dfs2(stk.top());
    int t;
    cin >> q;
    for(int i = 1; i <= q; i++)
    {
        cin >> t;
        if(flag[t]) cout << !res << endl;
        else cout << res << endl;
    }
    return 0;
}

CSP-J2022 T3 逻辑表达式:

题目传送门

和上一道题有异曲同工之处:

1.都是表达式

2.都需用DFS优化

不同的是给了中缀表达式

那么我们也可以得到本题思路:

1.建表达式树

2.DFS求值+计算短路次数

即可得到答案

代码:

#include <bits/stdc++.h>
using namespace std;
string s;
vector <int> vec[2000005];
char o[2000005];
int ans1, ans2, res;
int n, cnt;
int val[2000005];
string sf;
stack<int> ops;
void change()
{
	for(int i=0;i<s.size();i++)
	{
		if(s[i]=='0'||s[i]=='1')sf += s[i];
		else if(s[i]=='(')ops.push(s[i]);
		else if(s[i]==')')
		{
			while(!ops.empty()&&ops.top()!='(')
			{
				sf += ops.top();
				ops.pop();
			}
			ops.pop();
		}
		else if(s[i] == '&')
		{
			while(!ops.empty()&&ops.top()=='&')
			{
				sf += ops.top();
				ops.pop();
			}
			ops.push('&');
		}
		else
		{
			while(!ops.empty()&&ops.top() != '(')
			{
				sf += ops.top();
				ops.pop();
			}
			ops.push('|');
		}
	}
	while(!ops.empty())
	{
		sf += ops.top();
		ops.pop();
	}
}
void buildtree()
{
    change();
    //cout << sf << endl;
    stack<int> stk;
    for(int i = 0; i < sf.size(); i++)
    {
        if(sf[i] == '0' || sf[i] == '1')
        {
            val[++n] = sf[i] - '0';
            stk.push(n);
        }
        else if(sf[i] == '&' || sf[i] == '|')
        {
            int a = stk.top(); stk.pop();
            int b = stk.top(); stk.pop();
            stk.push(++cnt);
            vec[cnt].push_back(b);
            vec[cnt].push_back(a);
            o[cnt] = sf[i];
        }
    }
}
int dfs1(int root)
{
    if(root <= n) return val[root];
    if(o[root] == '|') return val[root] = dfs1(vec[root][0]) | dfs1(vec[root][1]);
    if(o[root] == '&') return val[root] = dfs1(vec[root][0]) & dfs1(vec[root][1]);
    return 0;
}
void dfs2(int root)
{
    if(o[root] == '&')
    {
        if(val[vec[root][0]] == 0)
            ans1++;
        else dfs2(vec[root][1]);
        dfs2(vec[root][0]);
    }
    if(o[root] == '|')
    {
        if(val[vec[root][0]] == 1)
            ans2++;
        else dfs2(vec[root][1]);
        dfs2(vec[root][0]);
    }
}
int main()
{
    cin >> s;
    n = 0;
    cnt = s.size() + 5;
    buildtree();
    dfs1(cnt);
    dfs2(cnt);
    cout << val[cnt] << "\n" << ans1 << " " << ans2 << endl;
    return 0;
}

关注劳大,让你们永远得吃

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值