# 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(); } ```