很简单的好吧
查看原帖
很简单的好吧
548591
sunsetglow楼主2022/11/13 10:49

const int N = 1e6+10;

// 栈,用来处理括号( ) stack st; // p[左括号下标]=右括号下标 p[2]=6 int p[N]; // 待计算的逻辑表达式 string s;

struct Result { // ans 逻辑表达式的值,x a&b的短路次数, y a|b的短路次数 int ans,x,y; };

// 计算a&b或者a|b Result cal(Result l,char op,Result r) { Result res; if(op == '&') { // 如果左边的数==0,就是a&b短路,a&b次数++,右边不计算 if(l.ans == 0) res = l,res.x++; // 如果左边的数==1,没有发生短路,左边的短路次数+右边的短路次数 else res = Result{r.ans,l.x+r.x,l.y+r.y}; } else { // 如果左边的数==1,就是a|b短路,a|b次数++,右边不计算 if(l.ans == 1) res = l,res.y++; // 如果左边的数==0,没有发生短路,左边的短路次数+右边的短路次数 else res = Result{r.ans,l.x+r.x,l.y+r.y}; } return res; }

// 递归求s[st...ed]范围内的表达式结果 Result solve(int st,int ed) { // 如果p[左括号下标]=右括号下标 p[2]=6 p[8]=16 if(p[st] == ed) { // 去掉括号计算 st+1,ed-1 return solve(st+1,ed-1); } // 否则进行正常运算 // res({0,0,0})表示最终答案,最终答案是|起来的,所以开始为0 // tmp表示当前一串连续的&的答案 // now表示当前一项的答案 // 三者关系 res(tmp|tmp|tmp) tmp(now&now&now) Result res{0,0,0},tmp{1,0,0},now{0,0,0}; // 从st循环到ed for(int i = st;i<=ed;i++) { // 如果s[i]是左括号 0&(1|0)|(1|1|1&0) p[2]=6 if(p[i]) { // 递归计算i+1,p[i]-1,p[i]是当前左括号对应的右括号的位置 now = solve(i+1,p[i]-1); // 0&(1|0)|(1|1|1&0) 计算1|0的结果保存到now,i跳转到pi')+1 i = p[i] + 1; } // 如果s[i]不是左括号,一定是一个值 else { // 先保存s[i] now = {s[i]-'0',0,0}; // i跳到下一个字符,下一个字符一定是一个运算符,或者越界 i++; } // 以上的if else就将当前的now拿出来了 // 计算结果,注意tmp({1,0,0})默认,因为1&任何数的结果取决于(等于)右边 // 此处是tmp&now的结果 tmp = cal(tmp,'&',now); // 接下来判断是否需要将结果|到res里面去 // 两种情况 i > ed判断是否越界,s[i] =='|'表示需要|操作 // 下一个字符是|,表示之后要计算|,先把tmp的结果|到res里面 // 0&(1|0)|(1|1|1&0) if(i > ed || s[i] =='|') { // 将res|tmp运算 res = cal(res,'|',tmp); // tmp重新赋初值 tmp = Result{1,0,0}; } } return res; }

int main() { // 0&(1|0)|(1|1|1&0) cin >> s; int n = s.length(); // 循环表达式,使用stack将表达式的括号关系记录到p数组 for(int i = 0;i<n;i++) { // 如果是左括号,将左括号的位置(下标)压入栈中 if(s[i] == '(') { st.push(i); } // 如果是右括号,将栈中的括号位置(下标)保存在p数组当中。 // p[左括号下标]=右括号下标 else if(s[i] == ')') { p[st.top()] = i; st.pop(); } } // p[2]=6 p[8]=16 /*for(int i = 0;i<100;i++) { if(p[i] != 0) cout << i <<" " << p[i]<<endl; } */ // 调用solve递归计算s[0...n-1]范围内的表达式结果 Result res = solve(0,n-1); cout << res.ans << endl; cout << res.x <<" " << res.y;

return 0;

}```cpp const int N = 1e6+10;

// 栈,用来处理括号( ) stack st; // p[左括号下标]=右括号下标 p[2]=6 int p[N]; // 待计算的逻辑表达式 string s;

struct Result { // ans 逻辑表达式的值,x a&b的短路次数, y a|b的短路次数 int ans,x,y; };

// 计算a&b或者a|b Result cal(Result l,char op,Result r) { Result res; if(op == '&') { // 如果左边的数==0,就是a&b短路,a&b次数++,右边不计算 if(l.ans == 0) res = l,res.x++; // 如果左边的数==1,没有发生短路,左边的短路次数+右边的短路次数 else res = Result{r.ans,l.x+r.x,l.y+r.y}; } else { // 如果左边的数==1,就是a|b短路,a|b次数++,右边不计算 if(l.ans == 1) res = l,res.y++; // 如果左边的数==0,没有发生短路,左边的短路次数+右边的短路次数 else res = Result{r.ans,l.x+r.x,l.y+r.y}; } return res; }

// 递归求s[st...ed]范围内的表达式结果 Result solve(int st,int ed) { // 如果p[左括号下标]=右括号下标 p[2]=6 p[8]=16 if(p[st] == ed) { // 去掉括号计算 st+1,ed-1 return solve(st+1,ed-1); } // 否则进行正常运算 // res({0,0,0})表示最终答案,最终答案是|起来的,所以开始为0 // tmp表示当前一串连续的&的答案 // now表示当前一项的答案 // 三者关系 res(tmp|tmp|tmp) tmp(now&now&now) Result res{0,0,0},tmp{1,0,0},now{0,0,0}; // 从st循环到ed for(int i = st;i<=ed;i++) { // 如果s[i]是左括号 0&(1|0)|(1|1|1&0) p[2]=6 if(p[i]) { // 递归计算i+1,p[i]-1,p[i]是当前左括号对应的右括号的位置 now = solve(i+1,p[i]-1); // 0&(1|0)|(1|1|1&0) 计算1|0的结果保存到now,i跳转到pi')+1 i = p[i] + 1; } // 如果s[i]不是左括号,一定是一个值 else { // 先保存s[i] now = {s[i]-'0',0,0}; // i跳到下一个字符,下一个字符一定是一个运算符,或者越界 i++; } // 以上的if else就将当前的now拿出来了 // 计算结果,注意tmp({1,0,0})默认,因为1&任何数的结果取决于(等于)右边 // 此处是tmp&now的结果 tmp = cal(tmp,'&',now); // 接下来判断是否需要将结果|到res里面去 // 两种情况 i > ed判断是否越界,s[i] =='|'表示需要|操作 // 下一个字符是|,表示之后要计算|,先把tmp的结果|到res里面 // 0&(1|0)|(1|1|1&0) if(i > ed || s[i] =='|') { // 将res|tmp运算 res = cal(res,'|',tmp); // tmp重新赋初值 tmp = Result{1,0,0}; } } return res; }

int main() { // 0&(1|0)|(1|1|1&0) cin >> s; int n = s.length(); // 循环表达式,使用stack将表达式的括号关系记录到p数组 for(int i = 0;i<n;i++) { // 如果是左括号,将左括号的位置(下标)压入栈中 if(s[i] == '(') { st.push(i); } // 如果是右括号,将栈中的括号位置(下标)保存在p数组当中。 // p[左括号下标]=右括号下标 else if(s[i] == ')') { p[st.top()] = i; st.pop(); } } // p[2]=6 p[8]=16 /*for(int i = 0;i<100;i++) { if(p[i] != 0) cout << i <<" " << p[i]<<endl; } */ // 调用solve递归计算s[0...n-1]范围内的表达式结果 Result res = solve(0,n-1); cout << res.ans << endl; cout << res.x <<" " << res.y;

return 0;

}

2022/11/13 10:49
加载中...