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. go与c互相调用

    此例子来自于go源码中,借此来和大家分享一下两者如何调用,网上很多文章语言不详,也没有一个完整的测试例子 目录结构 首先src 目录下有 testcgowin目录下: 这里的_obj目录是cgo生成的 ...

  2. 「HNOI2008」越狱

    题目链接 戳我 \(Solution\) 正难则反,这道题直接做有点困难,但我们可以反过来思考我们可以用总方案数减去不可以越狱的方案数 首先来算总方案数: 对于每个房间的人都有\(M\)种宗教可以选, ...

  3. Kotlin 函数

    至于什么函数,在计算机里面就是一个密闭的执行程序的代码块(个人理解) 我们先来看看什么是函数 fun main(agrs : Array<String>) { println(" ...

  4. javascript中var that=this

    在JavaScript中,this代表的是当前对象. $(‘#conten').click(function(){ //this是被点击的#conten var that = this; $(‘.co ...

  5. 51nod1464(trie + dfs)

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

  6. Java_Ant详解(转载)

    Java_Ant详解   1,什么是antant是构建工具2,什么是构建概念到处可查到,形象来说,你要把代码从某个地方拿来,编译,再拷贝到某个地方去等等操作,当然不仅与此,但是主要用来干这个3,ant ...

  7. 我的csdn博客地址

    呆雁 持续的谦虚与努力 http://blog.csdn.net/u013539183

  8. Jenkins持续集成企业实战系列之Jenkins配置演示-----03

    注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.    最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...

  9. luogu3703 [SDOI2017]树点涂色(线段树+树链剖分+动态树)

    link 你谷的第一篇题解没用写LCT,然后没观察懂,但是自己YY了一种不用LCT的做法 我们考虑对于每个点,维护一个fa,代表以1为根时候这个点的父亲 再维护一个bel,由于一个颜色相同的段一定是一 ...

  10. springcloud微服务架构的思考

    在网上找到一张关于微服务体系架构的图 应用组件: 首先对于整个程序的入口应该是网关,zuul部分 这个组件在springcloud中的gateway服务之后,zuul可以进行网关分配,根据想应的路劲进 ...