题意:给你n个括号字符串,排序这些括号字符串,怎么排序能使其配对最多,并输出总共有几个括号可以参与配对(配对成功的个数*2)。
配对就是 ' ) ' 前面只要出现 ' ( ' 就可以配对,不一定要连续,不过一个括号不能重复使用哈
多校赛的时候没看这题,其实不知道自己多校赛后面都干嘛去了。。一直在浪费时间啊。。。虽然不知道如果自己做能不能看懂这题怎么做,听完题解再做的。。
思路:
1、首先每个字符串输入之后先预处理一下每个字符串,计算出每个字符串里自己本身可以配对几个,有几个' ( ' 和 ' ) ' 还没进行配对,这里用栈就可以实现了。
2、然后进行排序,排序的话遵守一个原则,就是他们自己谁能对形成配对的贡献大
- 这个字符串里 ' ( ' 出现的次数比 ' ) ' 多,那么它就比较适合排左边(前面)
- ' ) '比较多的话适合排在后面,这样能够使自己对整个配对做出的贡献最大
- a和b比较的话,如果a和b ' ( ' 贡献相等时,谁的 ' ) ' 小就排前面,因为相对来说 ' ) ' 的要往后排,相对贡献会大一些
然后基本就是这样啦
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
struct Str{
int l, r, num; //l:(的数量 r: )的数量 num:匹配的数量
}str[maxn];
char s[maxn];
bool cmp(Str a, Str b){
if(a.l > a.r) //判断'('大于')'时,如果a,b都满足,则谁的')'小谁排前面,否则a排前面
return b.l > b.r? a.r<b.r:true;
return b.l <= b.r?a.l>b.l:false;
}
void init(int j){
stack<char> S;
int l = 0 ,r = 0, num = 0;
for(int i = 0; s[i]!= '\0'; i++){
if(s[i] == '('){
S.push('(');
l++;
}
else{
if(!S.empty()){
if(S.top() == '('){
S.pop();
num++;
l--;
}
else
r++;
}
else
r++;
}
}
str[j].l = l;
str[j].r = r;
str[j].num = num;
// printf("l = %d, r = %d, num = %d\n",l,r, num);
}
int main(){
int ans = 0, t, n, i;
scanf("%d",&t);
while(t--){
ans = 0;
scanf("%d",&n);
for(i = 1; i <= n; i++){
scanf("%s",s);
init(i);
ans += str[i].num;
}
sort(str+1, str+1+n, cmp);
int L = 0;
for(i = 1; i <= n; i++){
int temp = min(str[i].r,L);
L += str[i].l -temp;
ans += temp;
}
printf("%d\n",ans*2);
}
return 0;
}