https://vjudge.net/problem/UVA-1662
题意:
给出一个序列,判断序列中哪些括号是可以去掉的,只可以改变符号。输出括号最少的序列。
思路:
感觉这道题目就是写起来繁琐了点,我的代码比较啰嗦..
先保存每对括号的左右坐标,然后对于每一对括号,我们去寻找它前面和后面的符号,如果前后有乘除号并且括号内有加减号,那么这括号肯定是不能去掉的。另外的情况下都是可以去掉括号的,当然了,如果前面是减号或者是除号,有些符号需要相应的改变。
还有要注意一点,很重要!!
就是如果有对括号是不能去掉的,那么对于括号内的符号,我们需要标记一下。这样当我们考虑在它外面的大括号时,就不去考虑它里面的情况。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF=0x3f3f3f3f3f; 15 const int maxn=10000+5; 16 17 int cnt; 18 int len; 19 char str[maxn]; 20 int vis[maxn]; 21 22 struct node 23 { 24 int l,r; 25 int d; 26 bool operator<(const node& rhs) const 27 { 28 return d<rhs.d ||(d==rhs.d && l<rhs.l); 29 } 30 }a[maxn]; 31 32 33 int left_work(int L) 34 { 35 if(str[L]=='+') return 1; 36 else if(str[L]=='-') return 2; 37 else if(str[L]=='*') return 3; 38 else if(str[L]=='/') return 4; 39 else return -1; 40 } 41 42 int right_work(int R) 43 { 44 if(str[R]=='+') return 1; 45 else if(str[R]=='-') return 2; 46 else if(str[R]=='*') return 3; 47 else if(str[R]=='/') return 4; 48 else return -1; 49 } 50 51 52 int main() 53 { 54 // freopen("brackets.in","r",stdin); 55 //freopen("brackets.out","w",stdout); 56 //freopen("D:\input.txt","r",stdin); 57 while(~scanf("%s",str+1)) 58 { 59 cnt=0; 60 stack<int> sp; 61 memset(vis,0,sizeof(vis)); 62 63 len=strlen(str+1); 64 for(int i=1;i<=len;i++) 65 { 66 if(str[i]=='(') sp.push(i); 67 else if(str[i]==')') 68 { 69 int x=sp.top(); sp.pop(); 70 a[cnt].l=x; 71 a[cnt].r=i; 72 a[cnt].d=i-x; 73 cnt++; 74 } 75 } 76 77 sort(a,a+cnt); 78 /* 79 for(int i=0;i<cnt;i++) 80 cout<<a[i].l<<" "<<a[i].r<<endl; 81 */ 82 83 for(int i=0;i<cnt;i++) 84 { 85 bool flag=true; 86 int L=a[i].l,R=a[i].r; 87 88 int l_op=left_work(a[i].l-1); 89 int r_op=right_work(a[i].r+1); 90 91 //前后有乘除号但括号内有加减号 92 if(l_op==3||l_op==4||r_op==3||r_op==4) 93 { 94 for(int i=L+1;i<R;i++) 95 { 96 if(vis[i]==-1) continue; 97 if(str[i]=='+'||str[i]=='-') {flag=false;break;} 98 } 99 100 //不可变 101 if(!flag) 102 { 103 for(int i=L;i<=R;i++) 104 if(vis[i]==0) vis[i]=-1; 105 } 106 } 107 108 //处理前面无符号或为加号 109 if((l_op==-1||l_op==1)&&flag) 110 { 111 vis[L]=vis[R]=1; 112 } 113 114 115 //处理减号 116 if(l_op==2 && flag) 117 { 118 vis[L]=vis[R]=1; 119 for(int i=L+1;i<R;i++) 120 { 121 if(str[i]=='-' && vis[i]!=-1) str[i]='+'; 122 else if(str[i]=='+' && vis[i]!=-1) str[i]='-'; 123 } 124 } 125 126 //处理乘号 127 if(l_op==3 && flag) 128 { 129 vis[L]=vis[R]=1; 130 } 131 132 //处理除号 133 if(l_op==4 && flag) 134 { 135 vis[L]=vis[R]=1; 136 for(int i=L;i<=R;i++) 137 { 138 if(str[i]=='*' && vis[i]!=-1) str[i]='/'; 139 else if(str[i]=='/' && vis[i]!=-1) str[i]='*'; 140 } 141 } 142 } 143 144 for(int i=1;i<=len;i++) 145 { 146 if(vis[i]!=1) 147 printf("%c",str[i]); 148 } 149 printf(" "); 150 } 151 return 0; 152 }