CSU——2152: 小Z的表示式
Description
逆波蘭表示式 (Reverse(Reverse PolishPolish Notation,RPN)Notation,RPN) 是一種由波蘭數學家 JanJan ŁukasiewiczŁukasiewicz 於 19201920 年引入的數學表示式方式,在逆波蘭記法中,所有操作符置於運算元的後面,因此也被稱為字尾表示法。逆波蘭記法不需要括號來標識操作符的優先順序。
逆波蘭結構在 2020 世紀 6060 年代早期由 FriedrichFriedrich L.L. BauerBauer 和 EdsgerEdsger W.W. DijkstraDijkstra 獨立改造並提議用於表示式求值。澳大利亞哲學家和電腦科學家 CharlesCharles L.L. HamblinHamblin 在 2020 世紀 5050 年代中期擴充套件了該方案的演算法和符號。
一個一元運算使用逆波蘭記法的例子是階乘的記法: n!n!
在逆波蘭記法中,操作符置於運算元的後面。例如表達“三加四”時,寫作 “3“3 4+”4+” , 而不是 “3+4”“3+4” 。 如果有多個操作符,操作符置於第二個運算元的後面,所以常規中綴記法 “3−4+5”“3−4+5” 在逆波蘭記法中寫作 “3“3 4−5+”4−5+” , 使用逆波蘭記法的一個好處是不需要使用括號。
對於二元表示式,我們可以對其建立一棵二叉樹,,以基本運算物件作為葉結點中的資料,以運算子作為非葉節點中的資料,其兩棵子樹是它的運算物件,子樹可以是基本運算物件,也可以是複雜表示式。如圖就是一棵表示式樹。對錶達式樹進行後序遍歷(先遍歷左子樹,再遍歷右子樹,最後訪問根節點)就可以得到逆波蘭表示式。
現在小 Z 得到了若干棵表示式樹,但他不會轉換為逆波蘭表示式並求值,所以他想求助於你,請你幫助他將這些表示式樹轉換為逆波蘭表示式,並計算出其對應的值。
Input
第一行 TT ,代表資料組數(不超過 100100 組)
對於每組資料
首先一個 nn ,代表表示式樹的節點個數( 1≤n≤1000001≤n≤100000 )
接下來 nn 行,每行 xx , yy , zz ,第 ii 行代表對第 ii 個節點的描述,11 代表根節點
x=0x=0 代表這個節點是運算子, yy 是 “+”、“-”、“*”、“/” 四種運算子中的一個
x=1x=1 代表這個節點是運算元, yy 是其值, y∈[−1000,1000]y∈[−1000,1000]
zz 代表該節點的父親編號,根節點的父親編號為 00;
對於操作符的子樹,輸入中先出現的為其左子樹,後出現的為其右子樹。
資料保證運算中間過程和結果屬於 [−231,231−1][−231,231−1],且合法的除法均為整除
Output
對每一組陣列,輸出兩行
第一行為其表示式樹的逆波蘭表示式(以空格分隔)
第二行為其對應的值,如果運算中出現除以0的非法情況,則輸出“ERROR”(不含引號)
具體參見樣例輸出
Sample Input
2 11 0 - 0 0 + 1 1 7 2 0 * 2 1 8 4 0 / 1 1 6 6 1 3 6 0 - 4 1 5 9 1 2 9 5 0 / 0 1 3 1 0 - 1 1 6 3 1 6 3
Sample Output
7 8 5 2 - * + 6 3 / - 29 3 6 6 - / ERROR
這題是比賽的簽到題,但是時間都花在D上了,這題就是一道模擬我覺得,先建樹,然後後序遍歷去即可,基本上建樹的過程和Tire樹的建樹感覺差不多。
然後就是後序遍歷,開個stack儲存就行了。
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxn=100005;
const double eps=1e-8;
const double pi=acos(-1.0);
const int MOD=10056;
int T,n;
struct Node
{
int lson,rson;
int flag,num;
char op[2];
};
int p;
Node node[maxn];
stack<int>s;
void init()
{
while(!s.empty())
s.pop();
for(int i=1;i<=n;i++)
{
node[i].lson=-1;
node[i].rson=-1;
}
p=1;
}
int fun(int a,int b,char op)
{
if(op=='-')
return a-b;
if(op=='+')
return a+b;
if(op=='*')
return a*b;
if(op=='/')
{
if(b==0)
return INF;
else
return a/b;
}
}
void dfs(int x)
{
if(node[x].lson!=-1)
dfs(node[x].lson);
if(node[x].rson!=-1)
dfs(node[x].rson);
if(!node[x].flag)
{
printf("%c ",node[x].op[0]);
int a=s.top();s.pop();
int b=s.top();s.pop();
int num=fun(b,a,node[x].op[0]);
if(num==INF)
p=0;
s.push(num);
}
else
{
printf("%d ",node[x].num);
s.push(node[x].num);
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init();
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&node[i].flag);
if(node[i].flag==0)
scanf("%s",node[i].op);
else
scanf("%d",&node[i].num);
scanf("%d",&t);
if(!t)
continue;
if(node[t].lson!=-1)
node[t].rson=i;
else
node[t].lson=i;
}
int sum=0;
dfs(1);
printf("\n");
if(!p)
{
printf("ERROR\n");
continue;
}
sum=s.top();
s.pop();
printf("%d\n",sum);
}
return 0;
}
/**********************************************************************
Problem: 2152
User: jk1601zr
Language: C++
Result: AC
Time:4728 ms
Memory:3976 kb
**********************************************************************/