感觉这道题目并不是在考察图论相关的算法。首先是读入相应的括号对的信息,包括这对括号的开始位置、结束位置以及对应的长度,然后按照括号对的长度以及开始位置进行排序,然后逐个取出括号对来进行判断。首先判断对应的括号外面的符号,如果是乘除号,那么就判断对应的括号内部是否存在加减号,如果存在加减号,那么说明对应的括号是不能够删除的,并且内部的符号都是不能改变的,如果不存在加减号,那么括号可以删除,并且内部的符号都反转。如果括号的外部是加号,那么就可以直接删除括号,其他的保持不变;如果外部是减号,那么可以删除外部的括号,同时内部的加减号要进行反转,如果外部是乘号,同时内部没有加减号,那么括号可以直接进行删除;如果外部是除号,同时内部不存在加减号,那么外围的括号可以删除,同时内部的乘除号要进行反转。这里使用了一个数组visit,如果元素为0,代表的是符号可以改变,如果为-1,说明符号不能改变,如果为1,说明符号直接删除,最后输出那些剩余的符号即可,具体实现见如下代码:
#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
#include<functional>
using namespace std;
char data[1005];
class section{
public:
int start, end, length;
};
bool compare(const section a,const section b){
if (a.length != b.length) return a.length < b.length;
return a.start < b.start;
}
class Solve{
public:
int judge(int ind){
if (data[ind] == '+') return 1;
else if (data[ind] == '-') return 2;
else if (data[ind] == '*') return 3;
else if (data[ind] == '/') return 4;
return -1;
}
void Deal(){
vector<section> Section;
int L = strlen(data+1);
stack<int> st;
for (int i = 1; i <= L; i++){
if (data[i] == '(') st.push(i);
if (data[i] == ')'){
int x = st.top();
st.pop();
section temp;
temp.start = x;
temp.end = i;
temp.length = i - x + 1;
Section.push_back(temp);
}
}
sort(Section.begin(), Section.end(), compare);
int visit[1005];
memset(visit,0,sizeof(visit));//0代表可以变化
for (int i = 0; i < Section.size(); i++){
int l_flag = judge(Section[i].start - 1);
int r_flag = judge(Section[i].end + 1);
bool flag = true;
if (l_flag == 3 || l_flag == 4 || r_flag == 3 || r_flag == 4){//如果外部是乘除 内部不要有加减
for (int j = Section[i].start + 1; j < Section[i].end; j++){
if (visit[j] == -1) continue;//-1代表不可变化
if (data[j] == '+' || data[j] == '-'){
flag = false;//这个时候连同外面的符号都是不能删除的
break;
}
}
if (!flag){
for (int j = Section[i].start; j <= Section[i].end; j++)
if (visit[j]==0) visit[j] = -1;
}
}
if ((l_flag == 1 || l_flag == -1)&&flag){//如果外面的是加号 或者是没有符号
visit[Section[i].start] = 1;
visit[Section[i].end] = 1;
}
if (l_flag == 2&&flag){//如果外面的是减号 那么就将可以保留下来的加减号进行反转
visit[Section[i].start] = 1;
visit[Section[i].end] = 1;
for (int j = Section[i].start + 1; j < Section[i].end; j++){
if (visit[j] !=-1 && data[j] == '+') data[j] = '-';
else if (visit[j] !=-1 && data[j] == '-') data[j] = '+';
}
}
if (l_flag == 3 && flag){//处理对应的乘号 也就是直接去括号
visit[Section[i].start] = 1;
visit[Section[i].end] = 1;
}
if (l_flag == 4 && flag){//处理对应的除号
visit[Section[i].start] = 1;
visit[Section[i].end] = 1;
for (int j = Section[i].start ; j <= Section[i].end; j++){
if (visit[j] !=-1 && data[j] == '/') data[j] = '*';
else if (visit[j] !=-1 && data[j] == '*') data[j] = '/';
}
}
}
for (int i = 1; i <= L; i++){
if (visit[i] != 1) cout << data[i];
}
cout << endl;
}
};
int main(){
Solve a;
string s;
while (cin>>s){
memset(data,0,sizeof(data));
for (int i = 0; i < s.size(); i++) data[i + 1] = s[i];
a.Deal();
}
return 0;
}
//x/(y+z)/(a*(b-c)/d/(e/f))