题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5831
题目大意:给定一个由左右括号构成的字符序列,如果所有的左括号都能有一个右括号与之对应,则认为该序列是“正确的”,现在给出若干这样的序列,当然它们有可能是正确的,也有可能是不正确的,问,是否能通过其中两个字符的交换使得这个字符序列成为“正确的”(对于一个本来就正确的序列,也必须执行一次交换,也就是说对任何的序列必须且只需执行一次交换操作)。
解题思路:对于左右括号匹配的问题,首先想到的就是用栈来处理,因此,当我们得到一个字符序列的时候,就将它们一个个地压入栈中,若有能匹配的左右括号,则将这一对括号出栈,再继续将剩下的字符压栈,这样一来,栈中剩下的就是不能匹配的括号,通过判断剩下括号的数量以及情形来判断,思路如下:
(1)若剩余符号数为奇数,则必然不可能通过位置的调整得到“正确”序列;
(2)若剩余符号数大于或者等于6时,因为不匹配的括号太多,也不可能通过一次调整得到正确序列;
(3)若剩余符号数为4时,只有一种排列方式:))((,对于这种方式,只要将第一个括号与最后一个括号交换即可得到正确序列,因此,若剩余括号数为4时直接输出yes;
(4)若剩余符号数为2时,可能为: ) ( , ) ) , ( (,只有第一种情况可得到正确序列,特判即可
通过这四种情况的判断即可覆盖所有可能性,用代码实现即可
AC代码:
#include <iostream>
#include <stack>
using namespace std;
int main()
{
int t;
int n;
char c[100005];
cin>>t;
while(t--)
{
stack<char> ss;
ss.push('#');
cin>>n;
if(n==2)
{
char a,b;
cin>>a>>b;
if(a==')'&&b=='(')
{
cout<<"Yes"<<endl;
continue;
}
else
{
cout<<"No"<<endl;
continue;
}
}
else
{
cin>>c;
for(int i=0;i<n;i++)
{
char temp = ss.top();
if(temp=='('&&c[i]==')')ss.pop();
else ss.push(c[i]);
}
int len = ss.size()-1;
if(len>4)
{
cout<<"No"<<endl;
continue;
}
else if(len%2!=0)
{
cout<<"No"<<endl;
continue;
}
else if(len==4)
{
int lcnt=0;
int rcnt=0;
char str[4];
for(int i=3;i>=0;i--)
{
str[i] = ss.top();
if(str[i]=='(')lcnt++;
else rcnt++;
ss.pop();
}
if(lcnt!=rcnt)
{
cout<<"No"<<endl;
continue;
}
else
{
cout<<"Yes"<<endl;
continue;
}
}
else if(len==2)
{
int lcnt=0;
int rcnt=0;
char str[2];
for(int i=1;i>=0;i--)
{
str[i] = ss.top();
if(str[i]=='(')lcnt++;
else rcnt++;
ss.pop();
}
if(lcnt!=rcnt)
{
cout<<"No"<<endl;
continue;
}
else
{
cout<<"Yes"<<endl;
continue;
}
}
else
{
cout<<"Yes"<<endl;
continue;
}
}
}
return 0;
}