很好的一题贪心,自己死活想不出来怎么贪,一直去想几种特殊情况,比如(()()) , (()()())之类的,绕进死胡同了,这题关键是把已经匹配好的括号去掉,只考虑剩余部分怎么拼接才能最大化
看完这个博客思路后自己实现的时候除了点小问题,就是排序的时候出现死循环了,查了百度后可能原因是有相同的元素返回true导致不断排序,解决办法是让相同元素返回false或者使用stable_sort(),但是我用了之后还是wa了,可能还是排序写残了,博客里的解决办法是先把全都为)或者全都为(的串单独提出来,剩下的再进行排序就好了
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int mx = 1e5 + 5;
char stack[mx];
char str[mx];
struct node {
int left, right;
}pt[mx],l[mx],r[mx], mid[mx];
bool cmp(node a, node b) {
if (a.left >= a. right && b.left >= b.right) return a.right < b.right;
else if (a.left >= a.right) return true;
else if (b.left >= b.right) return false;
else return a.left > b.left;
}
int main() {
//freopen("1002.in", "r", stdin);
//freopen("out.txt", "w", stdout);
int T;
scanf("%d", &T);
while (T--) {
int n, ans = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%s", str);
int len = strlen(str);
int top = 0, cnt = 0;
pt[i].left = 0; pt[i].right = 0;
for (int j = 0; j < len; j++) {
if (str[j] == '(') {
pt[i].left++;
stack[top++] = '(';
}
else {
pt[i].right++;
if (top > 0 && stack[top-1] == '(') {top--; cnt++;}
else stack[top++] = ')';
}
}
ans += cnt; pt[i].left -= cnt; pt[i].right -= cnt;
//printf("ans = %d left = %d right = %d\n", ans, pt[i].left, pt[i].right);
}
int k1 = 0, k2 = 0, k3 = 0;
for (int i = 1; i <= n; i++) {
if (pt[i].left && pt[i].right == 0) l[++k1] = pt[i];
else if (pt[i].left == 0 && pt[i].right) r[++k3] = pt[i];
else mid[++k2] = pt[i];
}
sort(mid+1, mid+1+k2, cmp);
int top = 0;
for (int i = 1; i <= k1; i++) {
for (int j = 1; j <= l[i].left; j++)
stack[top++] = '(';
}
for (int i = 1; i <= k2; i++) {
//printf("pt[%d] %d %d\n",i, pt[i].left, pt[i].right);
for (int j = 1; j <= mid[i].right; j++) {
if (top > 0 && stack[top-1] == '(') {top--; ans++;}
else stack[top++] = ')';
}
for (int j = 1; j <= mid[i].left; j++)
stack[top++] = '(';
}
for (int i = 1; i <= k3; i++) {
for (int j = 1; j <= r[i].right; j++)
if (top > 0 && stack[top-1] == '(') {
top--; ans++;
}
}
printf("%d\n", ans*2);
}
return 0;
}