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. bzoj1798维护序列

    题目链接 暴力数据结构之线段树$qwq$ 裸题直接敲板子 忘了啥时候写的了$qwq$ 直接上代码吧 /************************************************* ...

  2. Github 三种克隆模式

    1.我称为平常模式,用于项目的本地克隆使用.(无权限.无加密.ssh protocol) git clone http://github.com/username/exampleproject 2.我 ...

  3. postgreSQL PL/SQL编程学习笔记(二)

    Control Structures of PL/SQL Control structures are probably the most useful (and important) part of ...

  4. 跟我一起读postgresql源码(三)——Rewrite(查询重写模块)

    上一篇博文我们阅读了postgresql中查询分析模块的源码.查询分析模块对前台送来的命令进行词法分析.语法分析和语义分析后获得对应的查询树(Query).在获得查询树之后,程序开始对查询树进行查询重 ...

  5. Unity---动画系统学习(4)---使用混合树(Blend Tree)来实现走、跑、转弯等的动画切换

    1. 介绍 Blend Tree用于多个动画之间的混合,比如走到跑的切换.转弯的切换. 如果用动画学习笔记(3)中的方法,需要新建很多的状态,不仅麻烦,而且切换状态时也很容易不流畅. 而Blend T ...

  6. SDUT OJ 顺序表应用2:多余元素删除之建表算法

    顺序表应用2:多余元素删除之建表算法 Time Limit: 3 ms Memory Limit: 600 KiB Submit Statistic Discuss Problem Descripti ...

  7. windows下Idea结合maven开发spark和本地调试

    本人的开发环境: 1.虚拟机centos 6.5 2.jdk 1.8 3.spark2.2.0 4.scala 2.11.8 5.maven 3.5.2     在开发和搭环境时必须注意版本兼容的问题 ...

  8. php常用的系统函数大全

    字符串函数 strlen:获取字符串长度,字节长度 substr_count 某字符串出现的次数 substr:字符串截取,获取字符串(按照字节进行截取) mb_strlenmb_substr str ...

  9. shell-004:检测机器存活或者网络陡动情况!

    如下图情况,我们监测的就是此数据,当大于50%了,我们就可以设置告警等! #!/bin/bash # 用ping检测一台机器的存活或者网络波动情况 # 检测机器的丢包率来检测网络波动情况!! n=`p ...

  10. alter table添加表约束

    翻阅了一下网上关于alter table添加表约束的资料,学习下,然后供自己以后使用. 仅仅供自己使用... 总结alter table ### add constraint ## 使用方法 添加表约 ...