• set(NOIP模拟赛Round 4)


    这题很神奇,对吧。

    标程还理解了好久,才明白。

    这道题需要用状压DP。首先我们看到总共只有15个字符串,所以可以用hash存储状态。

    然后我们还需要一维用来存储DP到第几个字符。

    所以dp[i][j]表示填到第i位后满足字符串的状态为j的个数;

    一开始我们将一个统计数定义为nj=j(j为状态);

    每次更新答案的时候只要从a到z枚举一遍,如果有不符合的地方那么nj-当前字符串所对应的二进制位(nj-=1<<l)

    统计答案的时候我们只需要for一遍,看看是否有一种状态的符合字符串的个数刚好为k,将dp答案加入总答案即可。

    下面贴代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mod 1000003
    #define mo(x)((x>=mod)?x-mod:x)
    #define match(a,b)((a=='?')||(b=='?')||(a==b))
    using namespace std;
    char str[16][51];
    int dp[51][1<<15];
    int n,k,ans;
    int main(){
    //    freopen("set.in","r",stdin);
    //    freopen("set.out","w",stdout);
        scanf("%d%d",&n,&k); 
        for(int i=0;i<n;i++)scanf("%s",str[i]);
        int qaq=strlen(str[0]); 
        dp[0][(1<<n)-1]=1;
        for(int i=0;i<qaq;i++)
        for(int j=1;j<(1<<n);j++)
            if(dp[i][j])
            {
                for(int k='a';k<='z';k++)
                {
                    int nj=j;                
                    for(int l=0;l<n;l++)
                    {
                        if(((j>>l)&1)&&(!match(str[l][i],k)))
                        nj-=(1<<l);
                    }
                    dp[i+1][nj]=mo(dp[i+1][nj]+dp[i][j]);
                }
            }
        for(int i=0;i<(1<<n);i++)
        {
            int count=0;
            for(int j=0;j<n;j++)count+=((i>>j)&1);
            if(count==k)ans=mo(ans+dp[qaq][i]);
        }
        printf("%d
    ",ans);
    //    fclose(stdin);
    //    fclose(stdout);
    } 
  • 相关阅读:
    Swift中枚举的总结以及使用
    CapsLock Enhancement via AutoHotKey
    计算思维
    计算几何-凸包算法 Python实现与Matlab动画演示
    CapsLock魔改大法——变废为宝实现高效编辑
    Python调用Matlab2014b引擎
    VC++如何利用Matlab2014b的图形引擎进行绘图
    Window中C++进行精确计时的方法
    十四。算法小知识点
    十三。宫水三叶公众号总结
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/6910047.html
Copyright © 2020-2023  润新知