Balanced Sequence HDU - 6299(杭电多校1 B)

时间:2024-01-07 14:54:38

题目说要n个字符串串内随意组合以后将这些串放在一起,然后求最长的括号匹配的长度,并不要求是连续的

因为不需要是连续的,所以可以先把已经匹配好的括号加入到答案里面去,先把这些删掉,以为并不影响结果,然后最后就只剩下))))((((这些的序列,然后接下来对剩下的考虑

因为剩下的括号最多只有四种情况就是

1.只有(   ((((((((

2.只有)   )))))))

3.(比)多  (((((())

4.)比(多   ))))))(((

然后我们要做的就是把他们排序,既然要得到尽可能多的匹配,那就贪心去排序,每次将(放在前面,把)放在后面,然后排序规则可以这样

1.先把 ( 全放进来

2.把 ( 比 ) 多的串放在前面

3.如果两个串都是 ( 比 ) 多,那就把 ) 少的放在前面

4.如果两个都是 ( 比 ) 少,那就把 ( 多的放在前面

5.最后再把全部都是 ) 的放在后面。

然后在扫一遍,L记录我扫到这个串的时候还有多少 ( 没有匹配,然后每次尽可能多的拿去匹配掉.

#include<map>
#include<set>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define first fi
#define second se
#define lowbit(x) (x & (-x)) typedef unsigned long long int ull;
typedef long long int ll;
const double pi = 4.0*atan(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = ;
const int maxm = ;
using namespace std; int n, m, tol, T;
struct Node {
int l, r;
Node () {
l = r = ;
}
bool operator < (Node a) const {
if(r == ) return ;
if(a.r == ) return ;
if(l >= r && a.l < a.r) return ;
if(l < r && a.l >= a.r) return ;
if(l >= r && a.l >= a.r) return r < a.r;
else return l > a.l;
}
};
Node node[maxn];
char str[maxn]; void init() {
memset(node, , sizeof node);
} int main() {
scanf("%d", &T);
while(T--) {
init();
scanf("%d", &n);
int ans = ;
for(int i=; i<=n; i++) {
stack<char> s;
scanf("%s", str+);
int len = strlen(str+);
for(int i=; i<=len; i++) {
if(str[i] == '(') s.push(str[i]);
if(str[i] == ')') {
if(!s.empty() && s.top() == '(') {
ans+=;
s.pop();
} else {
s.push(str[i]);
}
}
}
while(!s.empty()) {
char ch = s.top();
if(ch == '(') node[i].l++;
else node[i].r++;
s.pop();
}
}
sort(node+, node++n);
int L = ;
for(int i=; i<=n; i++) {
if(L >= node[i].r) {
ans += *node[i].r;
L -= node[i].r;
} else {
ans += *L;
L = ;
}
L += node[i].l;
}
printf("%d\n", ans);
}
return ;
}