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;
}
}
};