[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;
}
 
原文地址:https://www.cnblogs.com/yinwuxiao/p/9400580.html