---
# System prepended metadata

title: ZeroJudge j607. 3. 先加後乘與函數

---

# ZeroJudge j607. 3. 先加後乘與函數

其實看它配分就知道要解開這題，得分成兩個階段做：

```
(30 分): 運算式只包含數字、+和* 
(70 分): 無其他限制
```

因此以下將分成兩步驟解題

### 只包含數字、+和* 30分的思路

雖然題目有規定+和\*的優先規則，但其實可以發現因為只有 **兩個運算子** 需要考慮。
所以可以維護兩個變數，一個叫做prev、一個叫做now，分別代表之前 **加總** 的運算結果和現在處理中的運算結果。為了處理優先順序還需要建一個vector叫做res
然後遇到+就直接讓 now += prev，因為+的優先級最高；遇到\*就把prev放到res裡面並將prev歸零，因為乘法左側的加總和右側的加總不能牽扯在一起。
最後將prev和res裡面的所有元素相乘就是答案了

```cpp=
#include <bits/stdc++.h>

#define F first
#define S second

using namespace  std;
using ll = long long;

string s;

ll caculate(int begin, int end);

int parseInt(int front, int len) {
    return stoi(s.substr(front, len));
}

ll caculate(int begin, int end) {
    ll prev = 0, now = 0;
    vector<ll> res;
    while (begin <= end) {
        if (isdigit(s[begin])) {
            int tmp = begin;
            while (tmp <= end && isdigit(s[tmp])) {
                ++tmp;
            }
            now += parseInt(begin, tmp - begin);
            prev = now;
            now = 0;
            begin = tmp;
        } else if (s[begin] == '+') {
            now += prev;
            ++begin;
        } else if (s[begin] == '*') {
            res.emplace_back(prev);
            prev = 0;
            ++begin;
        }
    }
    
    if (res.empty()) {
        return prev;
    } else {
        ll ans = prev;
        for (ll i : res) {
            ans *= i;
        }
        return ans;
    }
}

void solve() {
    cin >> s;
    cout << caculate(0, (int)s.size() - 1) << "\n";
}

int main() {
    solve();
}
```

## AC的思路

與上面的差別其實只在函數f的加入而已，因為f內部每個逗號隔開的運算式都可以各自視為一條獨立的運算式，所以可以用遞迴處理。

這邊我是分成兩個函式解決：caculate()和f()

其實caculate()就和上面解法中的幾乎一樣，只差在增加遇到 'f' 時的行為而已；而f()就是單純將函數f的每個參數拆開後取最大最小值相減。

比較需要注意的是，函數f有時候會有嵌套的狀況發生，這時候得注意是否取到正確的右括號，不然一但遇到嵌套f，就會直接TLE

```cpp=
#include <bits/stdc++.h>

#define F first
#define S second

using namespace  std;
using ll = long long;

string s;

ll caculate(int begin, int end);
ll f(int begin, int end);

ll f(int begin, int end) {
    pair<ll, ll> ext = {LLONG_MIN, LLONG_MAX};
    int ignore = 0;
    while (begin <= end) {
        int tmp = begin;
        while (tmp <= end && (s[tmp] != ',' || ignore != 0)) {
            if (s[tmp] == '(') {
                ++ignore;
            } else if (s[tmp] == ')') {
                --ignore;
            }
            ++tmp;
        }
        ll res = caculate(begin, tmp - 1);
        ext.F = max(ext.F, res);
        ext.S = min(ext.S, res);
        begin = tmp + 1;
    }
    return ext.F - ext.S;
}

int parseInt(int front, int len) {
    return stoi(s.substr(front, len));
}

ll caculate(int begin, int end) {
    ll prev = 0, now = 0;
    vector<ll> res;
    while (begin <= end) {
        if (isdigit(s[begin])) {
            int tmp = begin;
            while (tmp <= end && isdigit(s[tmp])) {
                ++tmp;
            }
            now += parseInt(begin, tmp - begin);
            prev = now;
            now = 0;
            begin = tmp;
        } else if (s[begin] == 'f') {
            int tmp = begin + 2, cnt = 1;
            while (cnt) {
                if (s[tmp] == '(') {
                    ++cnt;
                } else if (s[tmp] == ')') {
                    --cnt;
                }
                ++tmp;
            }
            now += f(begin + 2, tmp - 2);
            prev = now;
            now = 0;
            begin = tmp;
        } else if (s[begin] == '+') {
            now += prev;
            ++begin;
        } else if (s[begin] == '*') {
            res.emplace_back(prev);
            prev = 0;
            ++begin;
        }
    }
    
    if (res.empty()) {
        return prev;
    } else {
        ll ans = prev;
        for (ll i : res) {
            ans *= i;
        }
        return ans;
    }
}

void solve() {
    cin >> s;
    cout << caculate(0, (int)s.size() - 1) << "\n";
}

int main() {
    solve();
}
```