- 解题思路
- 输入多组扩号字符串,自由排列,尽可能的让匹配的对数多。
- 先对单个字符串处理,把单一字符串中能匹配的括号配对出来。
- 队列按单边括号最少数排列(字符串连接配对的括号对数多)
- 把处理好的字符串入队
- 取出前两个字符串,按各自的左,右括号数确定,各自放在左还是右
- 再把5中的处理出的新字符串入队(没有就忽略)
- 直到无法再匹配,结束输出答案
代码
#include<ostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<stack>
using namespace std;
char s[100005];
struct node
{
int st;
int et;
bool operator <(const node a)const
{
return min(st,et)<min(a.st,a.et);
}
};
priority_queue<node> q;
stack<char> c;
int main()
{
int t,n,a,b,st,et,sum;
scanf("%d",&t);
while(t--)
{
while(!q.empty()) q.pop();
sum=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
a=0;b=0;
scanf("%s",&s);
int len=strlen(s);
for(int j=0;j<len;j++)
{
if(s[j]==')')
{
if(!c.empty()&&c.top()=='(')
c.pop();
else
c.push(s[j]);
}
else
c.push(s[j]);
}
while(!c.empty())
{
if(c.top()=='(')
a++;
else
b++;
c.pop();
}
sum+=(len-a-b)/2;
node now;
now.et=a;
now.st=b;
q.push(now);
}
while(!q.empty())
{
node now1,now2;
now1=q.top();
q.pop();
if(q.empty()) break;
now2=q.top();
q.pop();
if(min(now1.st,now2.et)>min(now1.et,now2.st))
{
swap(now1.st,now2.st);
swap(now1.et,now2.et);
}
sum+=min(now1.et,now2.st);
node ti;
if(now1.et>now2.st)
{
ti.et=now1.et-now2.st+now2.et;
ti.st=now1.st;
}
else
{
ti.st=now2.st-now1.et+now1.st;
ti.et=now2.et;
}
if(ti.et||ti.st)
q.push(ti);
}
printf("%d\n",sum*2);
}
}