题解:
一道比较好的题目
据说是个经典的贪心模型
首先我们会发现每个括号序列剩下的就是x个)和y个(
然后我们考虑怎么来进行贪心
首先比较显然的是我们会先用x<y的
并且很显然刚开始x需要=0
所以启发我们要对x从小到大排序
来证明一下这个的正确性
假设我们先取一个x比较大的,可能出现)已经比(多的情况
而我们是不希望这种情况出现的,而在贪心过程中,实际上(-)的数目是在不断增加的
那么考虑后半段
我刚开始以为然后就可以随便排了。。
然后测了一下就wa了
我们其实可以把右边看成左边的逆过程(因为我似乎不会正着证明。。。)
所以应该是按照)从大到小排序
代码:
#include <bits/stdc++.h>
#define rint register int
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
using namespace std;
const int N=310;
const int INF=1e9;
char c[N];
struct re{
int l,r,len;
}a[N*2];
int dp[N][N*N],n;
IL void maxa(int &x,int y)
{
if (x<y) x=y;
}
IL bool cmp(re x,re y)
{
if (x.l-x.r>=0&&y.l-y.r<0) return(1);
if (x.l-x.r<0&&y.l-y.r>=0) return(0);
if(x.l>x.r) return x.r<y.r;
else return x.l>y.l;
}
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n;
int cnt=0;
rep(i,1,n)
{
cin>>c;
int len; len=a[i].len=strlen(c);
int l=0,r=0;
rep(j,0,len-1)
{
if (c[j]==')')
if (l==0) r++; else l--;
else l++;
}
a[i].l=l; a[i].r=r;
if (a[i].l-a[i].r>0) cnt+=a[i].l-a[i].r;
}
sort(a+1,a+n+1,cmp);
rep(i,1,n+1)
rep(j,0,cnt) dp[i][j]=-INF;
dp[1][0]=0;
rep(i,1,n)
rep(j,0,cnt)
if (dp[i][j]>=0)
{
if (j>=a[i].r)
maxa(dp[i+1][j+a[i].l-a[i].r],dp[i][j]+a[i].len);
maxa(dp[i+1][j],dp[i][j]);
}
cout<<dp[n+1][0];
return 0;
}
来源:oschina
链接:https://my.oschina.net/u/4275712/blog/3883756