zoukankan      html  css  js  c++  java
  • BZOJ4416 SHOI2013阶乘字符串(状压dp)

      当n大到一定程度(>21)时一定无解,并不会证。

      如果要取出一个排列,显然应该让每一位在序列中的位置尽量靠前。于是设f[S]表示存在S子集中这些字母所组成的所有排列的最短前缀的长度,枚举当前排列最后一个字母转移即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 510
    #define M 21
    int T,n,m,a[N],f[1<<M],nxt[N][M];
    char s[N];
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4416.in","r",stdin);
        freopen("bzoj4416.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        T=read();
        while (T--)
        {
            m=read();scanf("%s",s+1);n=strlen(s+1);
            if (m>21) {cout<<"NO"<<endl;continue;}
            for (int i=1;i<=n;i++) a[i]=s[i]-'a';
            for (int i=0;i<m;i++) nxt[n][i]=nxt[n+1][i]=n+1;
            for (int i=n-1;i>=0;i--)
                for (int j=0;j<m;j++)
                nxt[i][j]=a[i+1]==j?i+1:nxt[i+1][j];
            memset(f,0,sizeof(f));
            int S=(1<<m)-1;
            for (int i=1;i<=S;i++)
                for (int j=0;j<m;j++) 
                if (i&(1<<j)) f[i]=max(f[i],nxt[f[i^(1<<j)]][j]);
            if (f[S]<=n) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
        return 0;
    }
  • 相关阅读:
    6.7-CU微程序设计
    6.6-CU组合逻辑设计
    6.5-CU的功能
    6.4-微操作命令的分析
    6.3-时序产生器
    6.2-指令的执行
    6.1-CPU的组成与功能
    5.3-指令格式设计
    【Java循环使用 + JS循环】
    JSON转换集合,报错exepct '[', but {, pos 1, json或者syntax error, expect {, actual [, pos 0
  • 原文地址:https://www.cnblogs.com/Gloid/p/9871112.html
Copyright © 2011-2022 走看看