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;
}

最新文章

  1. python基础之模块
  2. 基于HTML5的3D网络拓扑自动布局
  3. Tfs服务器迁移(更改IP)后客户端(vs2013)配置方法
  4. ACM一道关于素数查找的题
  5. Force removing ActivityRecord,app died, no saved state报错的理解
  6. 使用jxl.jar操作Excel
  7. JavaScript几种类工厂实现原理剖析
  8. myeclipse 8.5反编译插件失效
  9. 测试最新的log4cplus1.1.2版
  10. (转)asp.net(C#)手记之Repeater与两级菜单
  11. java开发中遇到的问题及解决方法(持续更新)
  12. [VC6 console]调用API获取手机归属地
  13. Codeforce 424C Magic Formulas 找规律
  14. SE 2014年4月30日
  15. iPad开发中UIPopoverController的使用
  16. 转:Apache 与 Nginx 比较
  17. jQuery淡入淡出的轮播图
  18. 关于SSH
  19. 海量并发的无锁编程 (lock free programming)
  20. 【C++】Lambda表达式

热门文章

  1. Android Camera相机功能实现 拍照并保存图片
  2. linux命令笔记,零散记录&lt;不完整,学习用&gt;
  3. win7系统电脑显示windows副本不是正版怎么办
  4. bzoj1798维护序列
  5. Tomcat8.5安装教程
  6. php 镜像richarvey/nginx-php-fpm的ngnix配置
  7. WebApi接口 - 响应输出xml和json 转
  8. JUC包下CountDownLatch学习笔记
  9. 创建逻辑卷LVM以及swap分区
  10. 005 Genymotion模拟器的使用和逍遥模拟器的使用