Bzoj 4922(字符串匹配新高度+DP)

来源:互联网 发布:seo教程网 编辑:程序博客网 时间:2024/05/28 18:43
题意:
现给定n个括号序列,你需要选择若干序列,将它们按一定的顺序从左往右拼接起来,得到一个合法的括号序列。计算可以得到的合法的括号序列的长度的最大值。
题解:

首先对于每个括号序列,把左边的左括号和右边的右括号对消,最后能得到一坨这样的东西:
))…))((…((
就是x个右括号然后y个左括号,记作(x,y)

然后考虑假如我们的子集选好了,我们要按照什么顺序拼接才能拼成一个合法的括号序列呢?

BZOJ3709
能拼必须满足当前左括号数x,拼完后左括号数+=yx
显然先拼yx的,后拼y<x

先考虑yx,显然拼了会使左括号数增大,那么能拼就拼,顺序是按照x从小到大

然后y<x,考虑倒着做,从后往前拼,能拼必须满足当前右括号数y,拼完后右括号数+=xy,所以顺序是按照y从小到大,正过来就是从大到小

那么我们把所有的二元组按照上述顺序排序后,以左括号数作为空间跑一遍背包就行了

注意由于物品大小有正有负所以要讨论一下枚举顺序。。。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<iostream>#include<algorithm>#include<stack>#include<queue>#include<vector>#include<set>#include<map>#include<string>using namespace std;typedef long long ll;typedef pair<int,int>P;const int INF=0x3f3f3f3f;const ll INFF=0x3f3f3f3f3f3f3f3f;const double pi=acos(-1.0);const double eps=1e-9;char str[505];int f[305][305*305];struct node{    int x,y,len;}a[305],a1[305],a2[305];bool cmp1(node p1,node p2){    return p1.x<p2.x;}bool cmp2(node p1,node p2){    return p1.x+p1.y>p2.x+p2.y;}int main(){    int n;    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        scanf("%s",str);        int len=strlen(str);        int now=0;        a[i].x=0;        for(int j=0;j<len;j++)        {            if(str[j]==')')                now--;            else                now++;            a[i].x=max(a[i].x,-1*now);        }        a[i].len=len;        a[i].y=now;    }    int cnt1=0,cnt2=0;    for(int i=1;i<=n;i++)    {        if(a[i].y>=0)            a1[++cnt1]=a[i];        else            a2[++cnt2]=a[i];    }    //printf("%d%d",cnt1,cnt2);    sort(a1+1,a1+cnt1+1,cmp1);    sort(a2+1,a2+cnt2+1,cmp2);    for(int i=1;i<=cnt2;i++)        a1[i+cnt1]=a2[i];    int s=0;    memset(f,0xef,sizeof(f));    f[0][0]=0;    for(int i=1;i<=n;i++)    {        for(int j=0;j<=s;j++)        {            f[i][j]=f[i-1][j];        }        for(int j=a1[i].x;j<=s;j++)        {            f[i][j+a1[i].y]=max(f[i][a1[i].y+j],f[i-1][j]+a1[i].len);        }        s+=a1[i].len;    }    printf("%d\n",f[n][0]);    return 0;}


原创粉丝点击