set(NOIP模拟赛Round 4)

Posted ghostfly233

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",ans);
//    fclose(stdin);
//    fclose(stdout);
} 

 

以上是关于set(NOIP模拟赛Round 4)的主要内容,如果未能解决你的问题,请参考以下文章

panel(NOIP模拟赛Round 4)

ping(NOIP模拟赛Round 4)第一次程序Rank 1!撒花庆祝!~(≧▽≦)/~

YYH的王国(NOIP模拟赛Round 6)

YYH的营救计划(NOIP模拟赛Round 6)

水(NOIP模拟赛Round #10)

calc(NOIP模拟赛Round 3)