zoukankan      html  css  js  c++  java
  • bzoj 1879 [Sdoi2009]Bill的挑战(状压DP)

     

    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。 

     

    【思路】

     

           状压DP

           f[i][s]表示前i-1个已经匹配,且匹配集合为s时的方案数。预处理出g[i][j]表示长度为i-1且最后一个字符为j的字符串集合。则有转移方程如下:      

                  f[i+1][s&g[i][k]]+=f[i][j]

     

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 
     5 const int N = 16 , M = 55;
     6 const int MOD = 1e6+3;
     7 
     8 int f[M][1<<N],g[M][26];
     9 char s[N][M];
    10 
    11 int T,n,K,len;
    12 
    13 int main() {
    14     scanf("%d",&T);
    15     while(T--) {
    16         memset(f,0,sizeof(f));
    17         memset(g,0,sizeof(g));
    18         scanf("%d%d",&n,&K);
    19         for(int i=0;i<n;i++)
    20             scanf("%s",s[i]);
    21         len=strlen(s[0]);
    22         for(int i=0;i<len;i++)
    23             for(int j=0;j<n;j++) {
    24                 if(s[j][i]!='?')
    25                     g[i][s[j][i]-'a']^=(1<<j);
    26                 else
    27                     for(int k=0;k<26;k++)
    28                         g[i][k]^=(1<<j);
    29             }
    30         int all=1<<n; f[0][all-1]=1;
    31         for(int i=0;i<len;i++)
    32             for(int j=0;j<all;j++) if(f[i][j])
    33                 for(int k=0;k<26;k++)
    34                     f[i+1][j&g[i][k]]=(f[i+1][j&g[i][k]]+f[i][j])%MOD;
    35         int ans=0,cnt;
    36         for(int j=0;j<all;j++) {
    37             cnt=0;
    38             for(int i=0;i<n;i++)
    39                 if(j&(1<<i)) cnt++;
    40             if(cnt==K) ans=(ans+f[len][j])%MOD;
    41         }
    42         printf("%d
    ",ans);
    43     }
    44     return 0;
    45 }

     

  • 相关阅读:
    CMake 从文件路径中提取文件名
    std::multimap 按照key遍历---
    Windows / Linux 一件编译zlib库
    C++ 11 可变模板参数的两种展开方式
    cmake 生成VS项目文件夹
    C++ 利用文件流复制文件
    利用 getsockname 和 getpeername 来获取某一个链接的本地地址和远端地址
    Windows 用VS编译libevent源码
    揭示同步块索引(上):从lock开始
    C手写一个多线程,供java调用
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5226861.html
Copyright © 2011-2022 走看看