• BZOJ-1879 Bill的挑战 状态压缩DP


    MD....怎么又是状压.......
    

    1879: [Sdoi2009]Bill的挑战
    Time Limit: 4 Sec Memory Limit: 64 MB
    Submit: 537 Solved: 280
    [Submit][Status][Discuss]

    Description
    这里写图片描述
    Input
    本题包含多组数据。 第一行:一个整数T,表示数据的个数。 对于每组数据: 第一行:两个整数,N和K(含义如题目表述)。 接下来N行:每行一个字符串。

    Output
    1
    2 1
    a?
    ?b

    Sample Input
    50

    Sample Output
    对于30%的数据,T ≤ 5,M ≤ 5,字符串长度≤ 20;
    对于70%的数据,T ≤ 5,M ≤ 13,字符串长度≤ 30;
    对于100%的数据,T ≤ 5,M ≤ 15,字符串长度≤ 50。

    HINT

    Source
    Day2

    一看数据范围,50?感觉不能状压啊...哦,M<=15.....
    

    思路比较简单:
    f【i】【j】表示 匹配到第i位,时状态为j的方案数;
    具体的转移:
    f[i+1][j&(g[i][l])]+=f[i][j],f[i+1][j&(g[i][l])]%=p;
    用g来存储状态,枚举状态即可;

    PS:当天晚上调了20多分钟没调完....被YveH神犇叫去颓废了,Carry了他一盘后睡觉去了...第二天调完1A辣
    

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    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;
    }
    #define p 1000003
    int t,n,k;
    char s[20][60];
    
    int f[60][1<<15],g[60][1<<5];
    void DP()
    {
        memset(f,0,sizeof(f)); memset(g,0,sizeof(g));
        int len=strlen(s[1]);
        for (int i=0; i<len; i++)
            for (int j=1; j<=n; j++)
                for (int l=0; l<26; l++)
                    if (s[j][i]=='?' || s[j][i]=='a'+l)
                        g[i][l]|=1<<(j-1);
        f[0][(1<<n)-1]=1;
        for (int i=0; i<len; i++)
            for (int j=0; j<(1<<n); j++)
                if (f[i][j]!=0)
                    for (int l=0; l<26; l++)
                        f[i+1][j&(g[i][l])]+=f[i][j],f[i+1][j&(g[i][l])]%=p;
        int ans=0;
        for (int i=0; i<(1<<n); i++)
            {
                int now=i,tmp=0;
                while (now) tmp+=now&1,now>>=1;
                if (tmp==k) ans=(ans+f[len][i])%p;
            }
        printf("%d
    ",ans);
    }
    
    int main()
    {
        t=read();
        while (t--)
            {
                n=read(),k=read();
                for (int i=1; i<=n; i++)
                    scanf("%s",s[i]);
                DP();
            }
        return 0;
    } 
  • 相关阅读:
    结对编程2—单元测试
    个人作业2—英语学习APP案例分析
    结对作业--基于GUI的四则运算生成器
    基于控制台的四则运算
    关于软件工程这门课
    个人作业3——个人总结(Alpha阶段)
    结对编程2——单元测试
    个人作业2——英语学习APP案例分析
    结对作业--基于GUI的四则运算生成器
    个人作业一
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346153.html
Copyright © 2020-2023  润新知