BZOJ-1879 Bill的挑战 状态压缩DP

来源:互联网 发布:java电子商务系统源码 编辑:程序博客网 时间:2024/06/09 16:27
MD....怎么又是状压.......

1879: [Sdoi2009]Bill的挑战
Time Limit: 4 Sec Memory Limit: 64 MB
Submit: 537 Solved: 280
[Submit][Status][Discuss]

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。

HINT

Source
Day2

一看数据范围,50?感觉不能状压啊...哦,M<=15.....

思路比较简单:
f【i】【j】表示 匹配到第i位,时状态为j的方案数;
具体的转移:
f[i+1][j&(g[i][l])]+=f[i][j],f[i+1][j&(g[i][l])]%=p;
用g来存储状态,枚举状态即可;

PS:当天晚上调了20多分钟没调完....被YveH神犇叫去颓废了,Carry了他一盘后睡觉去了...第二天调完1A辣

code:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int read(){    int x=0,f=1; char ch=getchar();    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}    return x*f;}#define p 1000003int t,n,k;char s[20][60];int f[60][1<<15],g[60][1<<5];void DP(){    memset(f,0,sizeof(f)); memset(g,0,sizeof(g));    int len=strlen(s[1]);    for (int i=0; i<len; i++)        for (int j=1; j<=n; j++)            for (int l=0; l<26; l++)                if (s[j][i]=='?' || s[j][i]=='a'+l)                    g[i][l]|=1<<(j-1);    f[0][(1<<n)-1]=1;    for (int i=0; i<len; i++)        for (int j=0; j<(1<<n); j++)            if (f[i][j]!=0)                for (int l=0; l<26; l++)                    f[i+1][j&(g[i][l])]+=f[i][j],f[i+1][j&(g[i][l])]%=p;    int ans=0;    for (int i=0; i<(1<<n); i++)        {            int now=i,tmp=0;            while (now) tmp+=now&1,now>>=1;            if (tmp==k) ans=(ans+f[len][i])%p;        }    printf("%d\n",ans);}int main(){    t=read();    while (t--)        {            n=read(),k=read();            for (int i=1; i<=n; i++)                scanf("%s",s[i]);            DP();        }    return 0;} 
0 0
原创粉丝点击