• 【BZOJ1879】【SDOI2009】Bill的挑战 [状压DP]


    Bill的挑战

    Time Limit: 4 Sec  Memory Limit: 64 MB
    [Submit][Status][Discuss]

    Description

      

    Input

      第一行:一个整数T,表示数据的个数。 
      对于每组数据: 
        第一行:两个整数,N和K(含义如题目表述)。 
        接下来N行:每行一个字符串。

    Output

      T行,每行一个整数表示答案

    Sample Input

      1
      2 1
      a?
      ?b

    Sample Output

      50

    HINT

      T ≤ 5,M ≤ 15,字符串长度≤ 50。

    Solution

      我们运用状压DP,令 g[i][c] 表示第 i 位,用 字符c匹配可行的串的集合

      然后显然就可以DP啦!f[i][opt] 表示做到了第 i 位匹配集合为opt的方案数。

    Code

     1 #include<iostream>    
     2 #include<string>    
     3 #include<algorithm>    
     4 #include<cstdio>    
     5 #include<cstring>    
     6 #include<cstdlib>
     7 #include<cmath>
     8 #include<queue>
     9 using namespace std;  
    10 typedef long long s64;
    11  
    12 const int ONE = 4e5 + 5;
    13 const int MOD = 1000003;
    14  
    15 int n, m, T;
    16 int g[52][52], f[52][32769];
    17 char s[25][52];
    18 int Ans;
    19  
    20 int get()
    21 {
    22         int res=1,Q=1;char c;
    23         while( (c=getchar())<48 || c>57 ) 
    24         if(c=='-')Q=-1; 
    25         res=c-48;     
    26         while( (c=getchar())>=48 && c<=57 )
    27         res=res*10+c-48;    
    28         return res*Q;
    29 }
    30  
    31  
    32 void Deal()
    33 {
    34         memset(g, 0, sizeof(g));
    35         memset(f, 0, sizeof(f));
    36         n = get();  m = get();
    37         for(int i = 1; i <= n; i++)
    38             scanf("%s", s[i] + 1);
    39  
    40         int len = strlen(s[1] + 1);
    41         for(int i = 1; i <= len; i++)
    42             for(int c = 1; c <= 26; c++)
    43                 for(int j = 1; j <= n; j++)
    44                     if(s[j][i] == '?' || s[j][i] == c + 'a' - 1)
    45                         g[i][c] |= 1 << j - 1;
    46  
    47         int total = (1 << n) - 1;
    48         f[1][total] = 1;
    49         for(int i = 1; i <= len; i++)
    50             for(int opt = 0; opt <= total; opt++)
    51                 if(f[i][opt])
    52                     for(int c = 1; c <= 26; c++)
    53                         (f[i + 1][opt & g[i][c]] += f[i][opt]) %= MOD;
    54  
    55         Ans = 0;
    56         for(int opt = 0; opt <= total; opt++)
    57         {
    58             int num = 0;
    59             for(int j = 1; j <= n; j++)
    60                 if(opt & (1 << j - 1)) num++;
    61             if(num == m) Ans = (Ans + f[len + 1][opt]) % MOD;
    62         }
    63  
    64         printf("%d
    ", Ans);
    65 }
    66  
    67 int main()
    68 {
    69         T = get();
    70         while(T--)
    71             Deal();
    72 }
    73 
    View Code
  • 相关阅读:
    iOS开发UI篇—Quartz2D使用(绘图路径)
    iOS开发UI篇—Quartz2D简单使用(三)
    iOS开发UI篇—Quartz2D使用(图片剪切)
    WordPress主题开发: 制作文章页面single.php
    Wordpress页面判断
    为WordPress某个文章添加额外的样式
    Wordpress本地伪静态设置
    Wordpress添加关键词和描述
    Wordpress制作sidebar.php
    Wordpress固定链接设置
  • 原文地址:https://www.cnblogs.com/BearChild/p/7630075.html
Copyright © 2020-2023  润新知