[BZOJ 1879][SDOI 2009]Bill的挑战 题解(状压DP)
[BZOJ 1879][SDOI 2009]Bill的挑战
Description

Solution
1.考虑状压的方式。
方案1:如果我们把每一个字符串压起来,用一个布尔数组表示与每一个字母的匹配关系,那么空间为26^50,爆内存;
方案2:把每一个串压起来,多开一维记录匹配字符,那么空间为nlen26,合法,但不便于状态的设计和转移;
方案3:把每一个串同一个位置的字符放在一起,用一个布尔数组记录与每一个小写字母的匹配关系,那么空间为26^15*len,爆内存;
方案4:把每一个串同一个位置的字符压起来,用多开一维的整形数组记录与每一个小写字母的匹配关系,空间为2^15*len,合法;
采用方案4,那么关系具体的记录方式就是,开一个压缩数组r[2^15][len],r[i][j]表示所有串第i位与第j个小写字母的匹配情况:
例如,第1到n个串的第i位分别为:?,a, b,c,那么他们与'a'的匹配情况为r[i][0]=0011;
void init(){
for(R int i=0;i<len;++i)//第i列
for(R int x=0;x<26;++x){//对'a'增量为x
r[i][x]=0;
for(R int k=0;k<n;++k)//第k个串
if(s[k][i]=='?'||s[k][i]=='a'+x)r[i][x]|=(1<<k);
}
}
2.考虑DP的过程
方案1:f[i][j]表示当前匹配长度位i,状态为j,实际上也就是符合要求的匹配情况为j时的方案数
方案2:f[i][j]表示当前匹配到第i位,状态为j时的方案数;
两种方案均可,只是第一种的i永远比第二种的i多1罢了。
但是我们要采用方案1,因为初始化时,未匹配情况应该只有一个那就是111...111,所以对于第一种情况初始化就非常简单,也就是f[0][(1<<n)-1]=1;
然后就是转移,我们发现当且仅当前一位时当前状态合法才可转移,我们转移采用扩展状态的方式,即在当前状态上枚举增加状态,所以状态转移方程是:
(f[i][j&r[i-1][x]]+=f[i-1][j])%=mod;
Code
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define R register
typedef long long ll;
using namespace std;
const int mod=1e6+3;
string s[20];
int n,m,r[51][50010],f[51][50010];
inline int lowbit(int x){return x&-x;}
void init(){
cin>>n>>m;
memset(f,0,sizeof(f));
for(R int i=0;i<n;++i)cin>>s[i];
int len=s[0].size();
for(R int i=0;i<len;++i)//第i列
for(R int x=0;x<26;++x){//对'a'增量为x
r[i][x]=0;
for(R int k=0;k<n;++k)//第k个串
if(s[k][i]=='?'||s[k][i]=='a'+x)r[i][x]|=(1<<k);
}
}
void work(){
int lim=(1<<n)-1;
int len=s[0].size();
f[0][lim]=1;
for(R int i=1;i<=len;++i)
for(R int j=0;j<=lim;++j)//状态
if(f[i-1][j])//如果当前前一列子集被更新过,即要扩展的状态合法
for(R int x=0;x<26;++x)//对'a'增量为x
(f[i][j&r[i-1][x]]+=f[i-1][j])%=mod;
int ans=0;
for(R int i=0;i<=lim;++i){
int temp=i,cnt=0;
while(temp){cnt++;temp-=lowbit(temp);}
if(cnt==m) (ans+=f[len][i])%=mod;
}
printf("%d\n",ans);
}
int main(){
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--){
init();
work();
}
return 0;
}
[BZOJ 1879][SDOI 2009]Bill的挑战 题解(状压DP)的更多相关文章
- BZOJ1879 [Sdoi2009]Bill的挑战 【状压dp】
题目 输入格式 本题包含多组数据. 第一行:一个整数T,表示数据的个数. 对于每组数据: 第一行:两个整数,N和K(含义如题目表述). 接下来N行:每行一个字符串. T ≤ 5,M ≤ 15,字符串长 ...
- bzoj 1879 [Sdoi2009]Bill的挑战(状压DP)
Description Input 本题包含多组数据. 第一行:一个整数T,表示数据的个数. 对于每组数据: 第一行:两个整数,N和K(含义如题目表述). 接下来N行:每行一个字符串. Output ...
- bzoj 1879: [Sdoi2009]Bill的挑战【状压dp】
石乐志写容斥--其实状压dp就行 设f[i][s]表示前i个字母,匹配状态为s,预处理g[i][j]为第i个字母是j的1~n的集合,转移的时候枚举26个字母转移,最后答案加上正好有k个的方案即可 #i ...
- BZOJ 1688: [Usaco2005 Open]Disease Manangement 疾病管理 状压DP + 二进制 + 骚操作
#include <bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) #defin ...
- 「BZOJ 5161」最长上升子序列「状压DP」
题意 求一个\(1\sim n\)的排列LIS的期望长度,\(n\leq 28\) 题解 考虑朴素的LIS:\(f[i] = min(f[j]) + 1\) 记\(mx[i]\)为\(f\)的前缀最大 ...
- 【50.54%】【BZOJ 1879】[Sdoi2009]Bill的挑战
Time Limit: 4 Sec Memory Limit: 64 MB Submit: 649 Solved: 328 [Submit][Status][Discuss] Descriptio ...
- 【BZOJ】1087: [SCOI2005]互不侵犯King(状压dp)
http://www.lydsy.com:808/JudgeOnline/problem.php?id=1087 状压dp是第一次写啊,我也是才学TAT.状压dp一般都用一个值表示集合作为dp的一个状 ...
- BZOJ 1097: [POI2007]旅游景点atr( 最短路 + 状压dp )
先最短路预处理, 然后状压就行了 -------------------------------------------------------------------------- #include ...
- 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)
2595: [Wc2008]游览计划 Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1572 Solved: 7 ...
随机推荐
- 了不起的Node.js--之二
安装模块 使用NPM包管理器可以让你轻松对模块进行管理,它会下载指定的包.解决包的依赖.进行测试脚本及安装命令行脚本. 安装二进制工具包 有的项目分发的是Node编写的命令行工具.这个时候,安装时要增 ...
- 《Linux内核分析》第二周笔记 操作系统是如何工作的
操作系统是如何工作的 一.函数调用堆栈 1.三个法宝 计算机是如何工作的?(总结)——三个法宝(存储程序计算机.函数调用堆栈.中断机制) 1)存储程序计算机工作模型,计算机系统最最基础性的逻辑结构: ...
- 读书笔记(chapter5)
系统调用 5.1与内核通信 1.系统调用在用户空间进程和硬件设备之间添加一个中间层.作用有三个:它为用户空间提供了一种硬件的抽象接口:系统调用保证了系统的稳定和安全:系统调用是用户空间访问内核的唯一手 ...
- 第二阶段Sprint7
昨天:将“录制”及“保存”整合到一起,修复出现的Bug,使之能够正常运行. 今天:把视频录制整合到时间提醒里,实现视频提醒 遇到的问题:额,整进去直接就停止运行了..也没有报错..
- [BUG随想录] 看不见的分隔符: Zero-width space
今天在调试一段代码的时候,有一个输入不能为空的库函数抛出了异常(为空就会抛出异常,就是这么傲娇).自己暗骂了自己一番,怎么这么大意,于是追溯源头,开始寻找输入控制的地方.但是当我找到时我惊呆了,我明明 ...
- win10下装上virtualbox 以及在virtualbox上装上 ubuntu 12.04
首先要下载virtual 在win10下可能第一步你就遇到了麻烦 首先刚开始我装的是最新版本的virtualbox 5.0.24.8355 (直接百度就可搜到) 然后可以按照这个教程 http://j ...
- 浅谈个人对存储区域网络SAN的理解
存储区域网络SAN,是一种通过将网络存储设备和服务器连接起来的网络,提供计算机和存储设备间的数据传输.其中,SAN是独立于服务器系统之外的,拥有近乎无限的存储能力,通过利用光纤作为传输媒介,实现了高速 ...
- Windows 设置开机自动登录
1. 自己一些windows的虚拟机 有时候开机之后 输入用户名密码时间特别长. 需要等待很久, 如果能够设置开机自动登录的话 能够节约很多时间. 2. 最简单的办法 运行输入 control us ...
- [转帖]ESXi 网卡绑定 增加吞吐量的方法
VMware ESX 5.0 网卡负载均衡配置3种方法 http://blog.chinaunix.net/uid-186064-id-3984942.html (1) 基于端口的负载均衡 (Rout ...
- Yii 框架的Rbac [权限控制]
转载自 xmlife 的博客 : http://blog.csdn.net/xmlife/article/details/50733451 1.首先我们要在配置文件的组件(component)里面配置 ...