zoukankan      html  css  js  c++  java
  • 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);
    } 
  • 相关阅读:
    HDU 4165 pills
    POJ 2125 Destroy The Graph
    POJ 2075 Tangled in Cables
    NYOJ Number SequenceProblem F
    PHP Eval研究笔记
    PHP 学习备忘(更新中)
    iOS学习笔记1 版本控制
    PHP全局缓存上栽的坑及其他【反面教材系列】
    iOS学习笔记2 Code Format
    iOS学习笔记4 垃圾回收初涉
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/6910047.html
Copyright © 2011-2022 走看看