a017. 五則運算 5/16/2025

解法一、遞迴

🔹 把大式子拆成小式子

依照 優先度由低而高、由後往前 的順序處理
+, -*, /, %(, )

當一個式子沒有任何運算符號(代表他只剩數字),返回數值
當一個式子運算完成,返回數值

例如測資 12 * 34 * 56 + 78
+ 明顯需要最後處理
於是由後往前找到 +
將問題拆成 12 * 34 * 56 + 78 兩個式子
先處理完這兩個式子後再處理加法

遞迴的代碼大概長做這樣

calculate(int begin, int end){
    // ...
    return calculate(int begin1, int end1) + calculate(int begin2, int end2);
    // ...
    return calculate(int begin1, int end1) * calculate(int begin2, int end2);

    // ...
    return num;
}

完整的步驟是 (中括號代表式子的拆法)

  1. + 號:[12 * 34 * 56] + [78]
  2. / 號:[[12 * 34] * 56] + [78]
  3. * 號:[[12 * 34] * 56] + [78]
  4. 返回結果:22926

另外由於括號要最後處理
因此需要一個變數 layer 紀錄當前位置括號的層數
當層數是 0 時,才能處裡 +, -, *, /, %

✅ 完整代碼

評分結果(參考) : AC (2ms, 332KB)

#include <bits/stdc++.h>
using namespace std;
#define int long long

string s;

int s2i(int begin_, int end_){
    int num = 0;
    for (int i=begin_; i<end_; i++) {
        num = num*10 + (s[i]-'0');
    }
    return num;
}

int calculate(int begin_, int end_) {

    if (begin_ >= end_) return 0;

    // handle + -
    int layer = 0;
    for(int i=end_-1; i>=begin_; i--) {
        if(s[i] == ')') layer++;
        else if(s[i] == '(') layer--;
        
        else if((s[i] == '+' || s[i] == '-') && layer == 0) {
            if(s[i] == '+') return calculate(begin_, i-1) + calculate(i+2, end_);
            else return calculate(begin_, i-1) - calculate(i+2, end_);
        }
    }

    // handle * / %
    layer = 0;
    for(int i = end_-1; i>=begin_; i--) {
        if(s[i] == ')') layer++;
        else if(s[i] == '(') layer--;
        
        else if(layer == 0) {
            if(s[i] == '*') return calculate(begin_, i-1) * calculate(i+2, end_);
            if(s[i] == '/') return calculate(begin_, i-1) / calculate(i+2, end_);
            if(s[i] == '%') return calculate(begin_, i-1) % calculate(i+2, end_);
        }
    }

    // handle ( )
    if(s[begin_] == '(' && s[end_-1] == ')') {
        return calculate(begin_+2, end_-2);
    }

    return s2i(begin_, end_);
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    while(getline(cin, s)) {
        cout << calculate(0, s.size()) << endl;
    }
}