【bzoj1879】【SDOI2009】【bill的挑战】【状压dp】
2016-03-31 18:43
369 查看
Description
Input
本题包含多组数据。 第一行:一个整数T,表示数据的个数。 对于每组数据: 第一行:两个整数,N和K(含义如题目表述)。 接下来N行:每行一个字符串。Output
12 1
a?
?b
Sample Input
50Sample Output
对于30%的数据,T ≤ 5,M ≤ 5,字符串长度≤ 20;对于70%的数据,T ≤ 5,M ≤ 13,字符串长度≤ 30;
对于100%的数据,T ≤ 5,M ≤ 15,字符串长度≤ 50。
题解:
因为M非常小,所以我们直接状压dp即可。
设f[i][j]表示到第i为,匹配的状态是j的方案数。
转移枚举用什么字母匹配即可。
最后把所有j中含有k个1的f[len][j]加起来即可。
代码:
#include<iostream> #include<cstdio> #include<cstring> #define P 1000003 using namespace std; int f[55][1<<16],ans,len,g[55][27],t,T,n,k; char ch[20][100]; int main(){ scanf("%d",&T); while (T--){ memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); scanf("%d%d",&n,&k);ans=0; for (int i=1;i<=n;i++) scanf("%s",ch[i]); f[0][(1<<n)-1]=1; len=strlen(ch[1]); for (int i=1;i<=len;i++) for (int j=0;j<26;j++) for (int k=1;k<=n;k++) if (ch[k][i-1]=='a'+j||ch[k][i-1]=='?') g[i][j]|=1<<(k-1); // for(int i=0;i<26;i++) cout<<i<<' '<<g[2][i]<<endl; for (int i=1;i<=len;i++) for (int j=0;j<(1<<n);j++) if (f[i-1][j]) for (int k=0;k<26;k++) (f[i][g[i][k]&j]+=f[i-1][j])%=P; for(int i=0;i<(1<<n);i++){ int t(0),x=i; while(x){if (x%2) t++;x/=2;} if (t==k) (ans+=f[len][i])%=P; } cout<<ans<<endl; } }
相关文章推荐
- Android的性能优化
- Android 短信验证码平台
- unity 链接 eclipse 调试
- 用wait和notify/notifyAll实现生产者消费者模式
- webmin1.791 ubuntu14.04现场体验篇
- 蝴蝶算法
- VxWorks串口发送
- BZOJ4127: Abs
- eclipse4.3怎么集成jadclipse追踪源代码,现在windows-preferences-java
- Python 2.7 学习笔记 访问mysql数据库
- 如何将wincc英文界面转化成中文
- 第四周总结日记
- 启动hive时:Hive Failed to connect to the MetaStore Server
- 免备案\免审批号\廉价教你构建自己的网站\域名DNS解析\超实用的端口映射转发
- Machine Learning--决策树(一)
- Linq 调试
- 最大的正方形
- R数据框合并(merge)的几种方式
- Intellij IDEA使用指南
- Aggregation is not enabled. Try the nodemanager at xingyunfei001.com.cn:50800