Description

Byteasar 组建了一支舰队!他们现在正在海洋上航行着。海洋可以抽象成一张n×m 的网格图,其中有些位置是“

.”,表示这一格是海水,可以通过;有些位置是“#”,表示这一格是礁石,不可以通过;有些位置是“o”,表

示这一格目前有一艘舰,且舰离开这一格之后,这一格将变为“.”。这些“o” 表示Byteasar 的舰队,他们每天

可以往上下左右中的一个方向移动一格,但不能有任何一艘舰驶出地图。特别地,Byteasar 对阵形有所研究,所

以他不希望在航行的过程中改变阵形,即任何时刻任何两艘舰的相对位置都不能发生变化。Byteasar 的舰队可以

航行无限长的时间,每当一艘舰经过某个格子的时候,这个格子海底的矿藏都将被Byteasar 获得。请写一个程序

,帮助Byteasar 计算他最多可以获得多少个格子海底的矿藏?

Solution

要解决两个问题

首先要求出原矩阵中的哪些子矩阵可以放下这个舰队所在的小矩阵

那么如果把障碍看作 \(1\),舰队所在的位置看作 \(1\),如果对应位置相乘不为都 \(1\),那么就是可以放的

我们把矩阵变成一个序列(把第二行接在第一行的后面,以此类推),实际上就是两个序列对应位置相乘不等于 \(1\)

把第二个序列反过来,就是一个卷积形式了,\(FFT\) 一遍就可以知道哪些位置是可以放舰队的了

能够放,但是不一定可以从初始矩阵走到,我们 \(bfs\) 一遍,把可以放且能走到的位置标为 \(1\),那么就是可以放舰队的位置了

舰队是一个矩阵,而且内部有障碍物,且直接计算答案会算重,复杂度也不对

一个格子的矿藏能获得当且仅当这个格子可以走到并且这个格子和某个时刻的舰队处于同一矩阵中

我们再把可以放且能走到的位置标为 \(1\),并且看作一个序列,并且和舰队对应的矩阵相乘,\(FFT\) 一下

结果中 \(1\) 的个数就是答案

复杂度 \(O(n*m*log)\)

#include<bits/stdc++.h>
using namespace std;
typedef complex<double> dob;
const int M=710,N=2e6+10;const double pi=acos(-1.0);
char s[M][M];int n,m,T[N],R[N],L=0,E;
inline void FFT(dob *A,int o){
for(int i=0;i<E;i++)if(i<R[i])swap(A[i],A[R[i]]);
for(int i=1;i<E;i<<=1){
dob wn(cos(pi/i),sin(o*pi/i)),x,y;
for(int j=0;j<E;j+=(i<<1)){
dob w(1,0);
for(int k=0;k<i;k++,w*=wn){
x=A[j+k];y=w*A[j+k+i];
A[j+k]=x+y;A[j+k+i]=x-y;
}
}
}
}
dob A[N],B[N];bool vis[M][M],d[N];
struct data{int x,y;};
int mx[4]={1,-1,0,0},my[4]={0,0,1,-1};
inline void bfs(data S){
memset(A,0,sizeof(A));
queue<data>Q;
Q.push(S);
while(!Q.empty()){
data t=Q.front();Q.pop();
for(int i=0;i<4;i++){
data u=(data){t.x+mx[i],t.y+my[i]};
if(t.x<0 || t.y<0)continue;
int v=u.x*m+u.y;
if(!vis[u.x][u.y] || d[v])continue;
d[v]=1;A[v]=1;Q.push(u);
}
}
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>n>>m;
int xl=N,xr=0,yl=N,yr=0;
for(int i=0;i<n;i++)scanf("%s",s[i]);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(s[i][j]=='#')B[i*m+j]=1;
else if(s[i][j]=='o'){
xl=min(xl,i);xr=max(xr,i);
yl=min(yl,j);yr=max(yr,j);
}
for(int i=xl;i<=xr;i++)
for(int j=yl;j<=yr;j++)
if(s[i][j]=='o')T[(i-xl)*m+j-yl]=1;
int r=(xr-xl+1),c=(yr-yl+1),len=(r-1)*m+c;
for(E=1;E<=n*m;E<<=1)L++;
for(int i=0;i<E;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
for(int i=0;i<len;i++)A[len-1-i]=T[i];
FFT(A,1);FFT(B,1);
for(int i=0;i<=E;i++)A[i]*=B[i];
FFT(A,-1);
for(int i=r-1;i<n;i++)
for(int j=c-1;j<m;j++)
if(!(int)(A[i*m+j].real()/E+0.5))vis[i][j]=1;
bfs((data){xr,yr});
for(int i=0;i<E;i++)B[i]=T[i];
FFT(A,1);FFT(B,1);
for(int i=0;i<=E;i++)A[i]*=B[i];
FFT(A,-1);
int ans=0;
for(int i=0;i<E;i++)if((int)(A[i].real()/E+0.5))ans++;
printf("%d\n",ans);
return 0;
}

bzoj 5217: [Lydsy2017省队十连测]航海舰队的更多相关文章

  1. BZOJ5217:[Lydsy2017省队十连测]航海舰队——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5217 Byteasar 组建了一支舰队!他们现在正在海洋上航行着.海洋可以抽象成一张n×m 的网格 ...

  2. BZOJ5217: [Lydsy2017省队十连测]航海舰队 FFT

    被FFT的空间卡了半天 后来发现根本不用开那么大... 首先可以把包含舰艇的那个小矩形找出来 将它一行一行连接成一个串T 其中舰艇位置为1其他位置为0 将大矩形也连成串S 其中礁石为1其他为0 两个串 ...

  3. bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树

    [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 93  Solved: 53[Submit][Status][ ...

  4. bzoj 5216: [Lydsy2017省队十连测]公路建设

    5216: [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 66  Solved: 37[Submit][St ...

  5. bzoj 5218: [Lydsy2017省队十连测]友好城市

    题意: 这题显然直接tarjan是做不了的. 这里安利另一个求SCC的算法Kosaraju,学习的话可以见这篇博客 于是结合莫队,我们有了个暴力. 发现主要瓶颈是dfs过程中找最小的未经过的点,我们用 ...

  6. BZOJ 5215: [Lydsy2017省队十连测]商店购物

    裸题 注意+特判 #include<cstdio> using namespace std; const int mod=1e9+7; int F[1000005],mi[10000005 ...

  7. @bzoj - 5219@ [Lydsy2017省队十连测]最长路径

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 在Byteland一共有n个城市,编号依次为1到n,形成一个n个 ...

  8. Lydsy2017省队十连测

    5215: [Lydsy2017省队十连测]商店购物 可能FFT学傻了,第一反应是前面300*300背包,后面FFT... 实际上前面背包,后面组合数即可.只是这是一道卡常题,需要注意常数.. //A ...

  9. 【BZOJ 5222】[Lydsy2017省队十连测]怪题

    题目大意: 传送门 给一个长度为$n(n<=200)$的数列$h$,再给$m$个可以无限使用的操作,第$i$个操作为给长度为花费$c_i$的价值给长度为$l_i$的数列子序列+1或-1,求将数列 ...

随机推荐

  1. openfiler的介绍与使用

    一. Openfiler简介 Openfiler 能把标准x86/64架构的系统变成一个强大的NAS.SAN存储和IP存储网关,为管理员提供一个强大的管理平台,并能能应付未来的存储需求.依赖如VMwa ...

  2. 解决git一直输入用户名和密码的问题

    git config --system --unset credential.helper,在git中输入此命令后,每次拉去代码需要重新输入用户名和密码,可以使用git config --global ...

  3. LoadRunner11_录制脚本时的浏览器版本

    最近在做的项目,因为浏览器类型及版本问题,浪费了很多时间,现在就此次的小折腾做一个小结,方便后期录制时选择(如果自己写脚本,那就可以完全忽略这些啦): (1)IE:win7   32位LR11.0,最 ...

  4. 51nod1464(trie + dfs)

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1464 题意: 中文题诶~ 思路: 将所有半回文串构建成一棵字 ...

  5. loj#6041. 「雅礼集训 2017 Day7」事情的相似度(后缀自动机+启发式合并)

    题面 传送门 题解 为什么成天有人想搞些大新闻 这里写的是\(yyb\)巨巨说的启发式合并的做法(虽然\(LCT\)的做法不知道比它快到哪里去了--) 建出\(SAM\),那么两个前缀的最长公共后缀就 ...

  6. [转]Resolving Python error: Unable to find vcvarsall.bat

    Resolving Python error: Unable to find vcvarsall.bat While installing python package flask-user usin ...

  7. 杀死进程命令 kill

    一般kill命令和ps命令结合使用, 例:现在想杀死telnet的进程 1.在所有进程中查看telnet命令 ps -ef |grep telnet 2.根据上面命令查到的进程id,如pid 是 xx ...

  8. ajax beforeSend中无效果

    asnyc:false 与beforesend 同时使用 无效果

  9. redis中使用lua脚本

    lua脚本 Lua是一个高效的轻量级脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能 使用脚本的好处 1.减少网络开销,在Lua脚 ...

  10. xml转换csv

    /// <summary> /// xml文件转换为CSV /// </summary> /// <param name="fileName"> ...