1. 程式人生 > >CSU——2152: 小Z的表示式

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
**********************************************************************/