码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1879 [Sdoi2009]Bill的挑战(状压DP)

时间:2016-02-29 12:14:53      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:

 

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\n",ans);
43     }
44     return 0;
45 }

 

 

bzoj 1879 [Sdoi2009]Bill的挑战(状压DP)

标签:

原文地址:http://www.cnblogs.com/lidaxin/p/5226861.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!