Boolean Evaluation:給定一個只含有1
、0
、&
、|
和^
的布爾表達式,求所有加括號的方式,使得該表達式的值爲result
,不考慮多餘括號的情況。
與其說加括號,不如說決定每個位運算符的被求值的順序,首先選定一個運算符作爲最後求值的運算符,該運算符將表達式分成了兩部分,在左右兩部分都被求值後,根據該運算符的運算規則,求出整個表達式的值。
基本思路有了,還需要稍微變化一下。因爲整個表達式的值已經確定爲result
了,所以要根據左右表達式取值真假的個數和運算符的含義,使用乘法公式計算。
class Solution {
public:
int countEval(string s, int result) {
expr.assign(s);
Count.assign(expr.size(), vector<pair<int, int>>(expr.size() + 1, pair<int, int>(-1, -1)));
return countEval(0, expr.size(), result == 1 ? true : false);
}
private:
string expr;
vector<vector<pair<int, int>>> Count;
int countEval(size_t begin, size_t end, bool bRes)
{
if(begin + 1 == end){
if(expr[begin] == '1' && bRes) return 1;
else if(expr[begin] == '0' && !bRes) return 1;
else return 0;
}
if(bRes && Count[begin][end].first != -1) return Count[begin][end].first;
if(!bRes && Count[begin][end].second != -1) return Count[begin][end].second;
int lt, lf, rt, rf, t;
pair<int, int> sum(0, 0);
for(size_t op = begin + 1; op < end; op += 2)
{
lt = countEval(begin, op, true);
lf = countEval(begin, op, false);
rt = countEval(op + 1, end, true);
rf = countEval(op + 1, end, false);
t = evalTrue(expr[op], lt, lf, rt, rf);
sum.first += t;
sum.second += (lt + lf) * (rt + rf) - t;
}
Count[begin][end] = sum;
if(bRes) return sum.first;
else return sum.second;
}
int evalTrue(char c, int lt, int lf, int rt, int rf)
{
switch(c)
{
case '&':
return lt * rt;
case '|':
return lt * (rt + rf) + lf * rt;
case '^':
return lt * rf + lf * rt;
default:
return 0;
}
}
};