1. 程式人生 > 其它 >201903-2二十四點

201903-2二十四點

前言

這是一道表示式求值的題目,而且還是簡單型別的,上學期老師也有給我們不知過這樣的作業,要求比這題還要難一點。但是,在我做的時候,我卻傻傻分不清四種運算子的優先順序,總是搞亂了。所以,我覺得,我還是有必要寫寫這一道題的。

題目(帶測試樣例)

題目連結附上:二十四點

這裡同樣給出題目的截圖:

測試樣例

10
9+3+4x3
5+4x5x5
7-9-9+8
5x6/5x4
3+5+7+9
1x1+9-9
1x9-5/9
8/5+6x9
6x7-3x6
6x4+4/5

思路

這個題目是用來做的,我的做法是建立一個數字棧和一個符號棧。然後下面我來講講我的思路

首先,我們得到的是一個字串,那麼我們要怎樣對它就行計算呢?那肯定就要進行轉換呀!數字字元就轉成我們的數字型別,符號字元就轉成我們能操作的運算子型別,這個應該是不用講的了。那麼,我們來關心一下,我們要怎樣進行運算呢?

我們回想一下,我們小時候學加減乘除時是不是有一個優先順序?比如說先乘除再加減,同級運算從左到右進行·······

好,我們只有四種運算,這兩條規則就夠了。

我們先把字串讀進來,然後對它進行分析,是數字的話就壓進數字棧,是符號的話就壓進符號棧,不過,在壓符號的時候,我們要注意些什麼?沒錯,注意它的優先順序。如果當前的字元的優先順序比棧頂元素的低,那我是不是要先把前面的運算執行完了才能壓入該符號?為什麼?

舉個例子,2*3+1,此時,我們判斷+該不該壓進堆疊,顯然不能,因為如果壓進堆疊的話,那麼我們進行運算的時候是不是會先算3+1?那這就不是我們的正確運演算法則了。我們的法則是先乘除,後加減,同級運算從左到右進行

,也就是說,就算是同級,我們前面壓進的字元也要比你後面壓進的字元優先順序要高,所以你後面的字元要壓進來的話,你要先等我前面的運算完才可以進棧。

好,這樣子,我們可以整出一個優先順序的表,這個表應該還有更多的符號,我這裡只是為了解這一道題,只給出以下四種,等我有時間了在補充寫一寫表示式求值的內容,到時後再將他們補全吧。

a\b + - * /
+ > > < <
- > > < <
* > > > >
/ > > > >

表格中的a代表棧頂符號,b代表當前要壓入的符號

這樣,我們觀察表格就會知道,只有到要壓進的符號為*

或者/的時候,它才能直接壓進去,否則都要將裡面有的符號先彈出計算才能壓進去。這是一個很好的規律,幫助我們減少程式碼量。

好,既然已經分析到這裡了,我想我們可以動手寫程式碼了。程式碼裡也有相應的註釋,不懂的朋友可以看一看程式碼。

程式碼

/* 二十四點 */
#include <bits/stdc++.h>
using namespace std;
/* 運算操作 */
int operate(int a, char b, int c) {
    if (b == '+') return a + c;
    if (b == '-') return a - c;
    if (b == 'x') return a * c;
    if (b == '/') return a / c;
}

int n;
int main() {
    cin >> n;
    stack<int> a;
    stack<char> b;
    while (n--) {
        string str;
        cin >> str;
        int len = str.length();
        for (int i = 0; i < len; i++) {
            if (isdigit(str[i])) {                                    //如果是數字,壓進數字棧
                a.push(str[i] - '0');
            } else {
                if (b.empty())       //字元棧為空的話直接壓棧
                    b.push(str[i]);
                else if ((b.top() == '+' || b.top() == '-') &&        //如果是字元,判斷優先順序,如果是特殊的那種情況,直接壓棧
                         (str[i] == 'x' || str[i] == '/')) {
                    b.push(str[i]);

                } else {                                              //否則先計算前面的
                    int num2 = a.top();
                    a.pop();
                    int num1 = a.top();
                    a.pop();
                    char c = b.top();
                    b.pop();
                    int num = operate(num1, c, num2);
                    a.push(num);
                    b.push(str[i]);
                }
            }
        }
        while (!b.empty()) {                                      //將堆疊裡面的符號全部拿出來計算
            int num2 = a.top();
            a.pop();
            int num1 = a.top();
            a.pop();
            char c = b.top();
            b.pop();
            int num = operate(num1, c, num2);
            a.push(num);
        }
        if (a.top() == 24)
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
        a.pop();
    }
    return 0;
}

寫在最後

這道題的表示式求值還是很簡單的一種形式,推薦大家去把全部的符號都考慮進去,比如括號這些,博主因為時間有限,就不寫了(明天就要考試了,五五)。以後有時間的話再來補充表示式求值的內容吧。好,那這道題就到這裡,謝謝您的閱讀哦。