ZOJ 1423 (Your)((Term)((Project))) (模拟+数据结构)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=423

Sample Input

3
(A-B + C) - (A+(B - C)) - (C-(D- E) )
((A)-( (B)))
A-(B+C)


Sample Output

A-B+C-(A+B-C)-(C-(D-E))
A-B
A-(B+C)

题目大意:给出加减代数表达式,仅由变量(大写字母表示),圆括号,加号 '+', 减号'-'组成,要求去掉多余的括号,但是不能改变表达式中的加号和减号,也就是说如果括号外面是减号,那就不能去掉

分析:

  对于每对括号标号,满足以下任意一个条件的就可以去掉,

  1.最外面的括号

  2.前面不是 减号 的括号

  3.前面是减号,但左右括号之间仅有变量,而没有 加减号 的括号。

第一反应是用栈做,但是STL的stack用在本题不方便,因为本题要遍历栈的元素,所以要自己写栈。

代码如下:

 1 # include<cstdio>
 2 # include<iostream>
 3 # include<cstring>
 4 # define MAX 300
 5 using namespace std;
 6 char str[MAX];    //输入
 7 char st[MAX];    //自定义栈
 8 int main(){
 9     int T;
10     scanf("%d",&T);
11     getchar();
12     while(T--){
13         int i,j;
14         gets(str);
15         int len=strlen(str);
16         st[0]=' ';    //如果第一个字符是'(',将情况1变成了情况2,少讨论
17         int tail=1;    //尾指针
18         for(i=0; i<len; i++){
19             if(str[i]==')'){
20                 bool flag = true;    //默认为括号里边不包含其他的'+'或'-' 
21                 for(j=tail-1; j>=1; j--){
22                     if(st[j]=='('){
23                         if(st[j-1]!='-'||st[j-1]=='-'&&flag)//括号前面不是减号 或者虽是减号但仅包含变量
24                             st[j]=' ';//取消该左括号,并且不要右括号,即不处理它
25                         else{
26                             st[tail++]='Y';    //代表右括号
27                             st[j]='X';        //代表左括号
28                         }
29                         break;
30                     }
31                     else{
32                         if(st[j]=='+'||st[j]=='-')
33                             flag = false;
34                     }
35                 }
36             }
37             else{
38                 if(str[i]!=' ')
39                     st[tail++]=str[i];
40             }
41         }
42         for(i=1; i!=tail; i++){    //遍历栈元素
43             if(st[i] != ' '){
44                 if(st[i] == 'X')
45                     cout<< "(";
46                 else if(st[i] == 'Y')
47                     cout<< ")";
48                 else
49                     cout<<st[i];
50             }
51         }
52         cout<<endl;
53     }
54     return 0;
55 }

 

附贴网上大部分人的思路:由于是模拟题,数据很小,直接暴力就好了。先扫描一次将空格去掉,再不断扫描,将(A)类型的括号去掉,直到不能去为止。再扫描一次,将所有括号用match数组匹配起来,若 s[i]==')' 那么 match[i]为与它匹配的'('所在的下标。再扫描一次,将'('前面不为负号的括号对全部标记mark[i]=1表示可以去掉。最后扫描一次,根据mark[i]数组将多余括号去掉~~~

 1 #include<stdio.h>
 2 #include<string.h>
 3 char s[258];
 4 int mark[258],match[258],zhan[258],num,opnum;
 5 int main()
 6 {
 7     int m,i,j,l,temp;
 8 
 9     scanf("%d",&m);
10     getchar();
11     while(m--)
12     {
13         gets(s);
14         memset(mark,-1,sizeof(mark));
15         memset(match,-1,sizeof(match));
16         for(l=strlen(s),i=j=0;i<l;i++)
17         {
18             if(s[i]==' ') continue;
19             s[j++]=s[i];
20         }
21         l=j,s[j]='\0',temp=1;
22         while(temp)
23         {
24             for(temp=j=i=0;i<l;i++)
25             {
26                 if(s[i]=='('&&s[i+2]==')')
27                     s[j++]=s[i+1],i=i+2,temp=1;
28                 else s[j++]=s[i];
29             }
30             l=j,s[j]='\0';
31         }
32         for(num=i=0;i<l;i++)
33         {
34             if(s[i]=='(') match[i]=i,zhan[num++]=i;
35             else if(s[i]==')') num--,match[i]=zhan[num];
36         }
37         for(i=0,temp=1;i<l;i++)
38         {
39             if(s[i]=='('&&temp==1) mark[i]=1;
40             else if(s[i]==')'&&mark[match[i]]==1) mark[i]=1;
41             if(s[i]=='-') temp=0;
42             else temp=1;
43         }
44         for(i=j=0;i<l;i++)
45         {
46             if(s[i]=='('&&mark[i]==1) continue;
47             else if(s[i]==')'&&mark[i]==1) continue;
48             s[j++]=s[i];
49         }
50         s[j]='\0';
51         printf("%s\n",s);
52     }
53 
54     return 0;
55 }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值