这题真是tmd……让我想起了做bohater时候的绝望
还好最后A了
注意到每个括号序列相当于必须在当前前缀和>=x的情况下才能选,选完之后前缀和会+y
那么就是bohater原题了,按那道题的顺序排序一下,然后DP即可,f[i][j]表示只用前i个串前缀和为0的最长长度
答案为f[n][0]
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 310
#define MAXM 1010
#define ll long long
#define eps 1e-8
#define MOD 1000000007
#define INF 1000000000
struct data{
int x;
int y;
int len;
};
int n;
char s[MAXN];
int f[MAXN][MAXN*MAXN];
data a[MAXN];
data b[MAXN];
int tot1,tot2;
int ans;
bool cmp1(const data &x,const data &y){
return x.x<y.x;
}
bool cmp2(const data &x,const data &y){
return x.x+x.y>y.x+y.y;
}
int main(){
int i,j;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%s",s+1);
a[i].x=0;
int now=0;
for(j=1;s[j];j++){
now+=s[j]=='('?1:-1;
a[i].x=max(a[i].x,-now);
}
a[i].len=j-1;
a[i].y=now;
}
for(i=1;i<=n;i++){
if(a[i].y>=0){
a[++tot1]=a[i];
}else{
b[++tot2]=a[i];
}
}
if(tot1){
sort(a+1,a+tot1+1,cmp1);
}
if(tot2){
sort(b+1,b+tot2+1,cmp2);
}
memset(f,0xef,sizeof(f));
f[0][0]=0;
for(i=1;i<=tot2;i++){
a[tot1+i]=b[i];
}
int s=0;
for(i=1;i<=n;i++){
for(j=0;j<=s;j++){
f[i][j]=f[i-1][j];
}
for(j=a[i].x;j<=s;j++){
f[i][j+a[i].y]=max(f[i][j+a[i].y],f[i-1][j]+a[i].len);
}
s+=a[i].len;
}
printf("%d\n",f[n][0]);
return 0;
}
/*
*/