[bzoj4922]Karp-de-Chant Number
题解:
一道比较好的题目
据说是个经典的贪心模型
首先我们会发现每个括号序列剩下的就是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; }