题目链接:1002 Balanced Sequence
题目大意
给你n个括号序列, 你可以重新排序这些序列, 然后拼接起来, 求最大的合法括号子序列
思路
先将每个序列的可以匹配的括号去掉, 最后剩下一个类似”))))(((“的序列, 用一个pair保存’)’和’(‘的数量, 按照’)’数量乘以’(‘数量乘积从大到小排序, 最后从第一个开始, 贪心地拼接序列, 看放到已有序列的左边还是右边更优, 哪边更优就放哪边
我也不知道为什么要按乘积排序
还可以按’)’数量从大到小排序, 然后一样的贪心, 一样能AC
还有一种排序方法是这样, 也能AC, first是’)’的数量, second是’(‘数量
bool cmp(const P&x, const P&y)
{
// return (1ll*x.second-x.first)>(1ll*y.second-y.first);//按乘积排序能AC
//return x.first > y.first;//按')'数量排序
int t1 = min(y.first, x.second), t2 = min(x.first, y.second);
if(t1 == t2) return x.second > y.second;
return t1 > t2;
}
三种排序方法都能AC, 不懂这题什么鬼
代码
Status | Time | Memory | Length | Lang |
---|---|---|---|---|
Accepted | 140ms | 2196kB | 1410 | G++ |
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 1e5 + 100;
typedef long long ll;
typedef pair<int, int> P;
P p[maxn];
int T;
int n;
char s[maxn];
char st[maxn];
int top;
bool cmp(const P&x, const P&y)
{
return (1ll*x.second*x.first)>(1ll*y.second*y.first);
}
int main()
{
for(scanf("%d", &T); T; --T)
{
scanf("%d", &n);
int ans = 0;
for(int i=0; i<n; ++i)
{
scanf("%s", s);
p[i].first = p[i].second = 0;
for(int j=0; s[j]!='\0'; ++j)
{
if(s[j] == '(') ++p[i].second;
else
{
if(p[i].second) --p[i].second, ++ans;
else ++p[i].first;
}
}
}
sort(p, p+n, cmp);
int l = 0, r = 0;
for(int i=0; i<n; ++i)
{
int t1 = min(l, p[i].second);
int t2 = min(r, p[i].first);
if(t1 > t2)
{
ans += t1;;
l -= t1;
p[i].second -= t1;
}
else
{
ans += t2;
r -= t2;
p[i].first -= t2;
}
l += p[i].first;
r += p[i].second;
}
printf("%d\n", ans*2);
}
return 0;
}