• [bzoj4922]Karp-de-Chant Number


    来自FallDream的博客,未经允许,请勿转载,谢谢。


    卡常数被称为计算机算法竞赛之中最神奇的一类数字,主要特点集中于令人捉摸不透,有时候会让水平很高的选手迷之超时。
    普遍认为卡常数是埃及人Qa'a及后人发现的常数。也可认为是卡普雷卡尔(Kaprekar)常数的别称。主要用于求解括号序列问题。
    据考证,卡(Qa'a)是古埃及第一王朝的最后一位法老。他发现并研究了一种常数,后世以他的名字叫做卡常数。卡特兰数的起源也是因为卡的后人与特兰克斯结婚,生下来的孩子就叫卡特兰,而他只是发表了祖传的家书而已。Sereja也是卡的后人,提出括号序列问题,也是从家书里得到的资料。然而Sereja为了不让这个秘密公开,于是隐瞒了这道题的真正做法。可是由于卡的后人不是各个都像卡特兰一样爱慕虚荣,这一算法也无法找到。“欲见贤人而不以其道,犹欲其入而闭之门也”。卡之常数的奥秘,需要以一颗诚心去追寻。
    现给定n个括号序列,你需要选择若干序列,将它们按一定的顺序从左往右拼接起来,得到一个合法的括号序列。
    显然,这个问题可以用卡常数解决,为了检验你是否会卡常数,请写一个程序,计算可以得到的合法的括号序列的长度的最大值。
    n<=300 
     
    合法的括号序列只要满足前缀和都大等于0并且总和是0就行了。
    预处理每个序列的和还有前缀最小值
    合法的括号序列可以看成两段接起来,分别由和是正的 和 和是负的组成。
    对于和是正的,按照前缀最小值排序之后背包dp
    负的也同理,翻转一下就是同样的做法了。
    复杂度n^3
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define MN 300
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    char st[MN+5][MN+5];
    int n,len[MN+5],mn[MN+5],f[MN*MN+5],g[MN*MN+5],mx[MN+5],top=0,top2=0,ans=0;
    struct data{int x,l,len;}q[MN+5],q2[MN+5];
    bool cmp(data x,data y){return x.x>y.x;}
    int main()
    {
        n=read();
        memset(f,128,sizeof(f));
        memset(g,128,sizeof(g));
        for(int i=1;i<=n;++i) 
        {
            scanf("%s",st[i]+1);
            for(int j=1;st[i][j];++j)
                len[i]+=st[i][j]=='('?1:-1,
                mn[i]=min(mn[i],len[i]);
            for(int j=strlen(st[i]+1),k=0;j;--j)
                k+=st[i][j]=='('?1:-1,mx[i]=max(mx[i],k);
            len[i]>=0?(q[++top]=(data){mn[i],len[i],strlen(st[i]+1)},0):
                      (q2[++top2]=(data){-mx[i],-len[i],strlen(st[i]+1)},0);
        }
        sort(q+1,q+top+1,cmp);
        sort(q2+1,q2+top2+1,cmp);
        f[0]=g[0]=0;
        for(int i=1;i<=top;++i)
            for(int j=i*MN;j>=q[i].l-q[i].x;--j)
                f[j]=max(f[j],f[j-q[i].l]+q[i].len);
        for(int i=1;i<=top2;++i)
            for(int j=i*MN;j>=q2[i].l-q2[i].x;--j)
                g[j]=max(g[j],g[j-q2[i].l]+q2[i].len);
        for(int i=MN*MN;~i;--i)
            if(f[i]>=0&&g[i]>=0) ans=max(ans,f[i]+g[i]);
        cout<<ans;
        return 0;    
    }
  • 相关阅读:
    BZOJ 3811: 玛里苟斯 线性基
    HDU 3949 XOR 线性基
    BZOJ 2115: [Wc2011] Xor 线性基 dfs
    BZOJ 3963 HDU3842 [WF2011]MachineWorks cdq分治 斜率优化 dp
    BZOJ 3262: 陌上花开 cdq分治 树状数组
    BZOJ 2653: middle 主席树 二分
    BZOJ 3524 [Poi2014]Couriers 主席树
    BZOJ 4826: [Hnoi2017]影魔 单调栈 主席树
    BZOJ 3956: Count 主席树 可持久化线段树 单调栈
    2018/4/9省选模拟赛 0分
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj4922.html
Copyright © 2020-2023  润新知