遞迴_表示式求值_CH1802_表示式計算
阿新 • • 發佈:2018-12-19
思路分析:
此處不使用棧求表示式值的演算法, 而使用遞迴演算法, 注意題目中指出表示式中可能存在多餘括號, 因此應首先去除多餘括號得到等價的合法表示式(使用棧進行配對即可), 接下來將表示式長度視為問題的規模, 為減小問題的規模實現遞迴, 根據運算子優先順序特點, 如果表示式中存在不在任何括號中的加減號, 那麼將最後一個不在任何括號中的加減號作為表示式分割點, 如果存在表示式中存在不在任何括號中的乘除號, 那麼將最後一個不在任何括號中的乘除號作為表示式分割點, 否則以最後一個不在任何括號中的乘方號作為表示式的分割點, 下面給出基於此思想AC程式碼(實際上, 可通過對錶達式長度進行數學歸納, 證明下述程式能正確計算表示式的值, 具體證明過程此處不再贅述)
//CH1802_表示式計算 #include <cstdio> #include <iostream> #include <list> #include <vector> #include <algorithm> #include <cmath> #include <cstring> using namespace std; const int MAX = 35, NIL = 0x3f3f3f3f; char cstr[MAX]; list<char> li; vector<list<char>::iterator> ve; vector<int> vee; int getRes(int l, int r){ int x = NIL, y = NIL, z = NIL;//x:cstr中最後一個不在括號中的加減號下標,y:乘除號,z:乘方號 for(int i = l; i <= r; ++i) if(cstr[i] == '(') vee.push_back(i); else if(cstr[i] == ')') vee.pop_back(); else if((cstr[i] == '+' || cstr[i] == '-') && vee.empty()) x = i; else if((cstr[i] == '*' || cstr[i] == '/') && vee.empty()) y = i; else if(cstr[i] == '^' && vee.empty()) z = i; if(x == NIL && y == NIL && z == NIL){ if(cstr[l] == '(') return getRes(l + 1, r - 1); int res = 0; for(int i = l; i <= r; ++i) res = res * 10 + cstr[i] - '0'; return res; } if(x != NIL) if(cstr[l] == '-') return -getRes(l + 1, r); else return cstr[x] == '+'? getRes(l, x - 1) + getRes(x + 1, r) : getRes(l, x - 1) - getRes(x + 1, r); if(y != NIL) return cstr[y] == '*'? getRes(l, y - 1) * getRes(y + 1, r) : getRes(l, y - 1) / getRes(y + 1, r); return pow((double)getRes(l, z - 1), getRes(z + 1, r)); } int main(){ int len = (scanf("%s", cstr + 1), strlen(cstr + 1)); for(int i = 1; i <= len; ++i) li.push_back(cstr[i]); for(list<char>::iterator it = li.begin(); it != li.end(); ++it) if(*it == '(') ve.push_back(it); else if(*it == ')' && !ve.empty()) ve.pop_back(); for(int i = 0; i < ve.size(); ++i) li.erase(ve[i]); copy(li.begin(), li.end(), cstr + 1); len = li.size(); cout << getRes(1, len) << endl; return 0; }