ACM-ICPC 2018 沈阳赛区网络预赛 B. Call of Accepted

题目连接
#题解
题目保证了xdy计算过程中x >= 0且y >= 1
重点就是读懂题目题意 然后逆波兰处理 最后计算处理后的值 注意每次处理完了情况栈即可
比赛时没做出来。。 后来参考一位大佬的博客写的代码
#AC代码

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int MAXN = 1e2 + 10;
char s[MAXN];

struct node
{
	ll l, r;
	char c; //操作符 为0则为值
};
queue<node> q;
stack<node> stk;
node operator + (const node &a, const node &b)
{
	return{ a.l + b.l, a.r + b.r };
}
node operator - (const node &a, const node &b)
{
	return{ a.l - b.r, a.r - b.l }; //a.l - b.r, a.r - b.l
}
node operator * (const node &a, const node &b)
{
	return{ min({ a.l * b.l, a.l * b.r, a.r * b.l, a.r * b.r }), max({ a.l * b.l, a.l * b.r, a.r * b.l, a.r * b.r }) };
}
node d(const node &a, const node &b)
{
	return{ a.l, a.r * b.r };
}
int Lv(char c)
{
	if (c == '+')
		return 1;
	if (c == '-')
		return 1;
	if (c == '*')
		return 2;
	if (c == 'd')
		return 3;
	return 0;
}
void ToRPN(char *s) //s逆波兰处理后存入q中
{
	int t = 0;
	for (int i = 0; s[i]; i++)
	{
		if (isdigit(s[i])) //数字 直接进队
		{
			if (!i || !isdigit(s[i - 1])) //数字第一位
				t = s[i] - '0';
			else
				t = t * 10 + s[i] - '0';
			if (!isdigit(s[i + 1])) //数字结束
				q.push({ t, t });
		}
		else if (s[i] == '(') //左括号 直接进栈
			stk.push({ 0, 0, s[i] });
		else if (s[i] == ')') //右括号 将上一个左括号后的操作全部进队
		{
			while (stk.top().c != '(')
				q.push(stk.top()), stk.pop();
			stk.pop();
		}
		else //其它操作符 将比自身优先级低或者相等的全部进队自身再进栈
		{
			while (!stk.empty() && Lv(s[i]) <= Lv(stk.top().c))
				q.push(stk.top()), stk.pop();
			stk.push({ 0, 0, s[i] });
		}
	}
	while (!stk.empty()) //全部进队
		q.push(stk.top()), stk.pop();
}
void CalRPN() //计算q中的逆波兰 答案存在stk中
{
	while (!q.empty())
	{
		int c = q.front().c;
		if (!c) //数字 直接进栈
			stk.push(q.front()), q.pop();
		else //操作符
		{
			q.pop();
			node lst = stk.top();
			stk.pop();
			node fst = stk.top();
			stk.pop();
			if (c == '+')
				fst = fst + lst;
			if (c == '-')
				fst = fst - lst;
			if (c == '*')
				fst = fst * lst;
			if (c == 'd')
				fst = d(fst, lst);
			stk.push(fst);
		}
	}
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	while (scanf("%s", s) != EOF)
	{
		ToRPN(s);
		CalRPN();
		cout << stk.top().l << " " << stk.top().r << endl;
		stk.pop();
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值