【bzoj4572 scoi2016】围棋
题目描述
近日,谷歌研发的围棋AI—AlphaGo以4:1的比分战胜了曾经的世界冠军李世石,这是人工智能领域的又一里程碑。
与传统的搜索式AI不同,AlphaGo使用了最近十分流行的卷积神经网络模型。在卷积神经网络模型中,棋盘上每一块特定大小的区域都被当做一个窗口。例如棋盘的大小为5*6,窗口大小为2*4,那么棋盘中共有12个窗口。此外,模型中预先设定了一些模板,模板的大小与窗口的大小是一样的。
下图展现了一个5*6的棋盘和两个2*4的模板。
对于一个模板,只要棋盘中有某个窗口与其完全匹配,我们称这个模板是被激活的,否则称这个模板没有被激活。
例如图中第一个模板就是被激活的,而第二个模板就是没有被激活的。我们要研究的问题是:对于给定的模板,有多少个棋盘可以激活它。为
了简化问题,我们抛开所有围棋的基本规则,只考虑一个n*m的棋盘,每个位置只能是黑子、白子或无子三种情况,换句话说,这样的棋盘共有3n*m种。此外,我们会给出q个2*c的模板。
我们希望知道,对于每个模板,有多少种棋盘可以激活它。强调:模板一定是两行的。
输入输出格式
输入格式:
输入数据的第一行包含四个正整数n,m,c和q,分别表示棋盘的行数、列数、模板的列数和模板的数量。随后2×q行,每连续两行描述一个模板。其中,每行包含c个字符,字符一定是'W','B'或'X'中的一个,表示白子、黑子或无子三种情况的一种。N<=100,M<=12,C<=6,Q<=5
输出格式:
输出应包含q行,每行一个整数,表示符合要求的棋盘数量。由于答案可能很大,你只需要输出答案对1,000,000,007取模后的结果即可。
题意:
nm的棋盘,有一个2*c的模板,nmc都比较小,求一共有多少种nm可以包含模板;
题解:
①反过来求不包含的方案数;
②aaarticlea/png;base64,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" alt="" />
轮廓线dp。。。。把模板串分成两份,用f[i][j][S][x][y]表示在ij位置,i行的ij和第一个模板匹配到了x,和第二个模板匹配到了y,S记录红色区域(只需记录m-c+1个)和第一个模板串匹配的情况。只有在S&(1<<m-c)&&y==c时不转移;
③ij可以不用存,滚动一下方便点,注意行更新时所有f[S][x][y]都要转移到f[S][0][0],初始状态为f[0][0][0] = 1,还有当x,y到了c时最后应该变成nxt[c];
③用kmp预处理nxt,再预处理出在i位置上加上j后的失配指针ta[i][j],tb[i][j];
#include<cstdio>
#include<iostream>
const int mod = 1e9+,N = ;
using namespace std;
int n,m,c,q,a[N],b[N],nxt[N],na,nb,f[(<<)][N][N],g[(<<)][N][N],ta[N][],tb[N][],U;
char gc(){
static char *p1,*p2,s[];
if(p1==p2) p2=(p1=s)+fread(s,,,stdin);
return (p1==p2)?EOF:*p1++;
}
int rd(){
int x=; char c = gc();
while(c<''||c>'') c = gc();
while(c>=''&&c<='') x=x*+c-'',c=gc();
return x;
}
char gt(){
char c; do c=gc(); while(!isalpha(c));
return (c=='W')?:(c=='B')?:;
}
void clear(){for(int S=;S<U;S++)for(int x=;x<c;x++)for(int y=;y<c;y++)g[S][x][y]=;}
void copy(){for(int S=;S<U;S++)for(int x=;x<c;x++)for(int y=;y<c;y++)f[S][x][y]=g[S][x][y];}
void up(int &x,int y){x+=y;if(x>=mod)x-=mod;}
int main()
{ freopen("bzoj4572.in","r",stdin);
freopen("bzoj4573.out","w",stdout);
n=rd();m=rd();c=rd();q=rd();
while(q--){
for(int i=;i<=c;i++) a[i] = gt();
for(int i=;i<=c;i++) b[i] = gt();
nxt[]=;
for(int i = ,j=;i <= c;nxt[i++]=j){
while(j&&a[j+]!=a[i]) j=nxt[j];
if(a[j+]==a[i]) j++;
}
na=nxt[c];
for(int i = ;i < c;i++) for(int j = ,k;j < ;j++){
for(k=i;k&&a[k+]!=j;k=nxt[k]);
if(a[k+]==j) k++; ta[i][j] = k;
}
nxt[]=;
for(int i = ,j=;i <= c;nxt[i++]=j){
while(j&&b[j+]!=b[i]) j=nxt[j];
if(b[j+]==b[i]) j++;
}
nb=nxt[c];
for(int i = ;i < c;i++) for(int j = ,k;j < ;j++){
for(k=i;k&&b[k+]!=j;k=nxt[k]);
if(b[k+]==j) k++; tb[i][j] = k;
}
U = (<<m-c+);
for(int S=;S<U;S++)for(int x=;x<c;x++)for(int y=;y<c;y++) f[S][x][y]=;
f[][][]=;
for(int i = ;i <= n;i++){
clear();
for(int S=;S<U;S++)for(int x=;x<c;x++)for(int y=;y<c;y++)if(f[S][x][y])up(g[S][][],f[S][x][y]);
copy();
for(int j=;j<=m;j++){
clear();
for(int S=;S<U;S++)for(int x=;x<c;x++)for(int y=;y<c;y++)if(f[S][x][y])for(int k=;k<;k++){
int E = S;
if(j>=c&&E&(<<j-c)) E^=(<<j-c);
int A = ta[x][k];
if(A==c){
E|=(<<j-c);
A=na;
}
int B = tb[y][k];
if(B==c){
if(S&(<<j-c)) continue;
B = nb;
}
up(g[E][A][B],f[S][x][y]);
}
copy();
}
}
int ans = ;
for(int i=;i<=n;i++)for(int j=;j<=m;j++) ans=1ll*ans*%mod;
for(int S=;S<U;S++)for(int x=;x<c;x++)for(int y=;y<c;y++) ans=(ans-f[S][x][y]+mod)%mod;
printf("%d\n",ans);
}
return ;
}//by tkys_Austin;
【bzoj4572 scoi2016】围棋的更多相关文章
- BZOJ4572: [Scoi2016]围棋
Description 近日,谷歌研发的围棋AI—AlphaGo以4:1的比分战胜了曾经的世界冠军李世石,这是人工智能领域的又一里程碑. 与传统的搜索式AI不同,AlphaGo使用了最近十分流行的卷积 ...
- 2019.03.25 bzoj4572: [Scoi2016]围棋(轮廓线dp)
传送门 题解可以参见zjjzjjzjj神仙的,写的很清楚. 代码: #include<bits/stdc++.h> #define ri register int using namesp ...
- [SCOI2016]围棋
Description 近日,谷歌研发的围棋AI-AlphaGo以4:1的比分战胜了曾经的世界冠军李世石,这是人工智能领域的又一里程碑.与传统的搜索式AI不同,AlphaGo使用了最近十分流行的卷积神 ...
- BZOJ.4572.[SCOI2016]围棋(轮廓线DP)
BZOJ 洛谷 \(Description\) 给定\(n,m,c\).\(Q\)次询问,每次询问给定\(2*c\)的模板串,求它在多少个\(n*m\)的棋盘中出现过.棋盘的每个格子有三种状态. \( ...
- 4572: [Scoi2016]围棋 轮廓线DP KMP
国际惯例的题面:这种题目显然DP了,看到M这么小显然要状压.然后就是具体怎么DP的问题.首先我们可以暴力状压上一行状态,然后逐行转移.复杂度n*3^m+3^(m*2),显然过不去. 考虑状态的特殊性, ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 一类巧妙利用利用失配树的序列DP
I.导入 求长度为\(\text{len}\)的包含给定连续子串\(\text{T}\)的 0/1 串的个数.(\(|T|<=15\)) 通常来说这种题目应该立刻联想到状压 DP 与取反集--这 ...
- 「SCOI2016」围棋 解题报告
「SCOI2016」围棋 打CF后困不拉基的,搞了一上午... 考虑直接状压棋子,然后发现会t 考虑我们需要上一行的状态本质上是某个位置为末尾是否可以匹配第一行的串 于是状态可以\(2^m\)压住了, ...
- 【LOJ】#2017. 「SCOI2016」围棋
题解 考虑到状态数比较复杂,其实我们需要轮廓线dp-- 我们设置\(f[x][y][S][h][k]\)为考虑到第(x,y)个格子,S是轮廓线上的匹配状态,是二进制,如果一位是1表示这一位匹配第一行匹 ...
随机推荐
- IE bug:ajax请求返回304解决方案
bug说明: 同一账户下的默认收货地址只有一个,默认收货地址可以修改,修改完成后,使用ajax重新加载收货地址部分. 默认收货地址状态标记:status = 1: 在IE浏览器做了修改后,重新加载的数 ...
- jstree的简单用法
一般我们用jstree主要实现树的形成,并且夹杂的邮件增删重命名刷新的功能 下面是我在项目中的运用,采用的是异步加载 $('#sensor_ul').data('jstree', false).emp ...
- VMware虚拟机误删除vmdk文件后如何恢复?
故障描述: Dell R710系列服务器(用于VMware虚拟主机),Dell MD 3200系列存储(用于存放虚拟机文件),VMware ESXi 5.5版本,因意外断电,导致某台虚拟机不能正常启动 ...
- 部分和问题 nyoj
部分和问题 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 给定整数a1.a2........an,判断是否可以从中选出若干数,使它们的和恰好为K. 输入 首先, ...
- Spring Security入门(3-7)Spring Security处理页面的ajax请求
- MySQLdb、 flask-MySQLdb 、MySQL-python 安装失败
今天在学习flask的时候,学习到数据库部分,连接mysql生成表,运行程序报错误:No module named MySQLdb 此时 需要安装 以下两个中任何一个 pip install flas ...
- JavaScript中Global、Math、Date对象的常用方法
JavaScript当中Global.Math.Date类型常用方法如下: /* js 中 Global对象 是一个不存在的对象,它里面的方法可以调用 常用方法: 1 encodeURI 对uri进行 ...
- 编码注释coding: utf-8
# -*- coding: utf-8 -*- PY文件当中是不支持中文的,即使你输入的注释是中文也不行,为了解决这个问题,就需要把文件编码类型改为UTF-8的类型,输入这个代码就可以让PY源文件里面 ...
- EF5中 执行 sql语句使用Database.ExecuteSqlCommand 返回影响的行数 ; EF5执行sql查询语句 Database.SqlQuery 带返回值
一: 执行sql语句,返回受影响的行数 在mysql里面,如果没有影响,那么返回行数为 -1 ,sqlserver 里面 还没有测试过 using (var ctx = new MyDbConte ...
- 六,前端---viewport
移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,再具体一点,就是浏览器上用来显示网页的那部分区域,但viewport又不局限于浏览器可视区域的大小,它可能比浏览器的可视区 ...