我的思路是把表达式做成树结构,然后从根节点开始计算,如果左边短路了就跳过右边,结果全WA了就对了4个点
求教
代码如下
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
struct node
{
int left;//左子节点
int right;//右子节点
char value;//0,1,|,&
};
string input;
node tree[1000005];//树
int befor_after[1000005];//存储括号连接
//栈记录括号连接
int stack[1000005];//辅助数组记录括号连接
int top=0;
int point_id=1;//分配了几个id
//递归划分树结构
void get_tree(int id/*分配给哪个节点*/,int l/*开始位置*/,int r/*结束位置*/)//确定3个值:id的内容,左子节点,右子节点
{
if(input[l]=='('&&input[r]==')'&&befor_after[l]==r&&befor_after[r]==l)//如果左右有多余括号嵌套
get_tree(id,l+1,r-1);//l+1,去左括号;r+1,去右括号
else if(input[l]=='0'||input[l]=='1')//[0/1]+[|/&]+[(乌七八糟的东西,不一定被括号包裹)/[0/1]]
{
//确定左子节点
point_id++;
tree[id].left=point_id;
tree[point_id].value=input[l];
if(r-l+1/*区域长度*/==3)//划分后没有剩余
{
//不考虑不符合规范吧?
//确定内容
tree[id].value=input[l+1];
//确定右子节点
point_id++;
tree[id].right=point_id;
tree[point_id].value=input[r];
}
else//有剩余
{
//确定内容
tree[id].value=input[l+1];
//设置右子节点
point_id++;
tree[id].right=point_id;
//递归分配右子节点
get_tree(tree[id].right,l+2,r);
}
}
else if(input[l]=='('/*乌七八糟的东西,必然被括号包裹*/&&(input[r]=='0'||input[r]=='1'))//[(乌七八糟的东西)]+[|/&]+[0/1]
{
//确定内容
tree[id].value=input[r-1];
//确定右子节点
point_id++;
tree[id].right=point_id;
tree[point_id].value=input[r];
//确定左子节点
point_id++;
tree[id].left=point_id;
//递归分配左子节点
get_tree(tree[id].left,l,r-2);
}
else if(input[l]=='('&&input[r]==')'&&befor_after[l]!=r&&befor_after[r]!=l)//[(乌七八糟的东西,必然被括号包裹)]+[|/&]+[(乌七八糟的东西,必然被括号包裹)]
{
//确定内容
tree[id].value=input[befor_after[l]+1];
//确定左子节点
point_id++;
tree[id].left=point_id;
//确定右子节点
point_id++;
tree[id].right=point_id;
//递归分配左子节点
get_tree(tree[id].left,l,befor_after[l]);
//递归分配右子节点
get_tree(tree[id].right,befor_after[r],r);
}
}
int short_or=0;//|短路
int short_and=0;//&短路
//递归计算
void get_ans(int id/*求解的标号*/)//tree[id].value被改为计算结果
{
//如果左子节点没有被求解,先求解左子节点
if(tree[id].left=='&'||tree[id].right=='|')
{
get_ans(tree[id].left);
}
//查看有无短路
if(tree[id].left=='0'&&tree[id].value=='&')
{
tree[id].value='0';
short_and++;
return;
}
else if(tree[id].left=='1'&&tree[id].value=='|')
{
tree[id].value='1';
short_or++;
return;
}
//如果右子节点没有被求解,先求解右子节点
if(tree[id].right=='&'||tree[id].right=='|')
{
get_ans(tree[id].right);
}
//求解
if(tree[id].value=='|')
{
if(tree[id].left=='1'||tree[id].right=='1')
tree[id].value='1';
else
tree[id].value='0';
}
else if(tree[id].value=='&')
{
if(tree[id].left=='0'||tree[id].right=='0')
tree[id].value='0';
else
tree[id].value='1';
}
return;
}
int main()
{
cin>>input;
input=" "+input;//为方便起见从1开始编号
int n=input.length()-1;//数据规模
//确定括号的前后连接
for(int i=1;i<=n;i++)
{
if(input[i]=='(')
{
top++;
stack[top]=i;
}
else if(input[i]==')')
{
befor_after[i]=stack[top];
befor_after[stack[top]]=i;
top--;
}
}
//生成树
get_tree(1/*1为根节点*/,1/*从1开始分配*/,n/*到n结束*/);
//计算,又递归计算
get_ans(1);
cout<<tree[1].value<<endl;
cout<<short_and<<" "<<short_or;
}