Description
Byteasar 组建了一支舰队!他们现在正在海洋上航行着。
海洋可以抽象成一张n×m 的网格图,其中有些位置是“.”,表示这一格是海水,可以通过;有些位置是“#”,表示这一格是礁石,不可以通过;有些位置是“o”,表示这一格目前有一艘舰,且舰离开这一格之后,这一格将变为“.”。
这些“o” 表示Byteasar 的舰队,他们每天可以往上下左右中的一个方向移动一格,但不能有任何一艘舰驶出地图。特别地,Byteasar 对阵形有所研究,所以他不希望在航行的过程中改变阵形,即任何时刻任何两艘舰的相对位置都不能发生变化。
Byteasar 的舰队可以航行无限长的时间,每当一艘舰经过某个格子的时候,这个格子海底的矿藏都将被Byteasar 获得。请写一个程序,帮助Byteasar 计算他最多可以获得多少个格子海底的矿藏?

Input
第一行包含两个正整数n;m,分别表示地图的长和宽。
接下来n 行,每行有m 个字符,每个字符只能是“.”、“#”、“o” 中的一个。
输入数据保证至少有一个“o”。

Output
输出一行一个整数,即可以被经过的格子数的最大值。

Sample Input
4 5
…#
.o#.o
.o…o
…o…

Sample Output
12

Data Constraint

分析:
我们先找到一个最小的矩阵可以包含所有船。然后相当于在原图中对这个进行匹配。
可以考虑使用fft进行匹配,把原图中#设为1,船的矩阵中船设为1,然后匹配。可以得出每个节点成为矩阵左上角是否合法。
因为有的点合法但是到不了,所以我们要从初始点进行bfs求出可以到达的合法点。
一个节点可以到达满足左上角合法这个位置有船。可以用所有可以到达的合法点与船继续fft,大于0的点都可以到达。

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>const int N=2e6+7;
const int maxn=707;
const double pi=acos(-1);
const int dx[4]={0,1,0,-1};
const int dy[4]={1,0,-1,0};using namespace std;int n,m,len,ans;
int f[N],g[N],r[N];
bool vis[maxn][maxn];
char a[maxn][maxn];struct node{int x,y;
};queue <node> h;struct rec{double x,y;
}x[N],y[N],z[N],w[N];rec operator +(rec a,rec b)
{return (rec){a.x+b.x,a.y+b.y};
}rec operator -(rec a,rec b)
{return (rec){a.x-b.x,a.y-b.y};
}rec operator *(rec a,rec b)
{return (rec){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};
}void fft(rec *a,int f)
{for (int i=0;i<len;i++){if (i<r[i]) swap(a[i],a[r[i]]);}w[0]=(rec){1,0};for (int i=2;i<=len;i*=2){rec wn=(rec){cos(2*pi/i),f*sin(2*pi/i)};for (int j=i/2;j>=0;j-=2) w[j]=w[j/2];for (int j=1;j<i/2;j+=2) w[j]=w[j-1]*wn;for (int j=0;j<len;j+=i){for (int k=0;k<i/2;k++){rec u=a[j+k],v=a[j+k+i/2]*w[k];a[j+k]=u+v;a[j+k+i/2]=u-v;}}}
}void FFT(int *a,int *b,int *c,int n,int m)
{len=1;int k=0;while (len<(n+m)) len*=2,k++;for (int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(k-1));for (int i=0;i<len;i++){int A,B;if (i<n) A=a[i]; else A=0;if (i<m) B=b[i]; else B=0;x[i]=(rec){A,0};y[i]=(rec){B,0};}fft(x,1),fft(y,1);for (int i=0;i<len;i++) z[i]=x[i]*y[i];fft(z,-1);for (int i=0;i<len;i++) c[i]=trunc(z[i].x/len+0.5);
}int get(int x,int y)
{return (x-1)*m+y-1;
}int main()
{freopen("sailing.in","r",stdin);freopen("sailing.out","w",stdout);scanf("%d%d",&n,&m);for (int i=1;i<=n;i++) scanf("%s",a[i]+1);   int lc,rc,ls,rs,p,q;lc=ls=m;rc=rs=0;for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){if (a[i][j]=='o'){lc=min(lc,i);ls=min(ls,j);rc=max(rc,i);rs=max(rs,j);}}}   p=rc-lc+1,q=rs-ls+1;for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){f[get(i,j)]=(a[i][j]=='#');if (a[i][j]=='o') g[get(i-lc+1,j-ls+1)]=1;}}reverse(f,f+n*m);   FFT(f,g,f,n*m,n*m);reverse(f,f+n*m);   vis[lc][ls]=1;h.push((node){lc,ls});while (!h.empty()){node d=h.front();h.pop();int x=d.x,y=d.y;for (int i=0;i<4;i++){if ((x+dx[i]>0) && (y+dy[i]>0) && (x+dx[i]<=n-p+1) && (y+dy[i]<=m-q+1)){if ((!f[get(x+dx[i],y+dy[i])]) && (!vis[x+dx[i]][y+dy[i]])){vis[x+dx[i]][y+dy[i]]=1;h.push((node){x+dx[i],y+dy[i]});}}}}memset(f,0,sizeof(f));for (int i=1;i<=n-p+1;i++){for (int j=1;j<=m-q+1;j++){f[get(i,j)]=vis[i][j];}}FFT(f,g,f,n*m,n*m);for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){if (f[get(i,j)]) ans++;}}printf("%d",ans);
}

jzoj 5062.【GDOI2017第二轮模拟day1】航海舰队 fft相关推荐

  1. GDOI2017第二轮模拟day1 总结

    平民比赛 这场比赛的暴力分非常友好. 但是我并没有拿到全部的暴力分. 1(暴力分\(60/100\)) 暂时我可以拿的暴力分为\(30/100\),直接mst模拟即可. 然而当时打了个辣鸡莫队,结果爆 ...

  2. 【GDOI2017第二轮模拟day1】公路建设

    Description 在Byteland一共有n 个城市,编号依次为1 到n,它们之间计划修建m条双向道路,其中修建第i 条道路的费用为ci. Byteasar作为Byteland 公路建设项目的总 ...

  3. 【JZOJ5064】【GDOI2017第二轮模拟day2】友好城市 Kosarajo算法+bitset+ST表+分块

    题面 在Byteland 一共有n 座城市,编号依次为1 到n,这些城市之间通过m 条单向公路连接. 对于两座不同的城市a 和b,如果a 能通过这些单向道路直接或间接到达b,且b 也能如此到达a,那么 ...

  4. JZOJ 5068. 【GDSOI2017第二轮模拟】树

    Description 有n个点,它们从1到n进行标号,第i个点的限制为度数不能超过A[i]. 现在对于每个s (1 <= s <= n),问从这n个点中选出一些点组成大小为s的有标号无根 ...

  5. 【JZOJ B组】【GDSOI2017第二轮模拟】奶酪

    题目 Description CJY很喜欢吃奶酪,于是YJC弄到了一些奶酪,现在YJC决定和CJY分享奶酪. YJC弄到了n-1块奶酪,于是他把奶酪挂在了一棵n个结点的树上,每根树枝上挂一块奶酪,每块 ...

  6. 【GDOI2017第三轮模拟day1】影魔(主席树)

    Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄. 每一个 ...

  7. 【JZOJ5073】【GDOI2017第三轮模拟day1】影魔

    Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄. 每一个 ...

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

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

  9. 【题解】CSP-J2021第二轮题解

    CSP-J2021第二轮题解 T1.分糖果 ⊗ \otimes ⊗ 简化题目:给定 l , r l,r l,r,求 max ⁡ i = l r ( i m o d n ) \max_{i=l}^{r} ...

最新文章

  1. NetworkInfo 方法过时的处理方法
  2. R语言使用psych包的fa函数对指定数据集进行因子分析(输入数据为相关性矩阵)、使用rotate参数指定进行斜交旋转提取因子、使用nfactors参数指定抽取的因子个数、fa函数因子分析结果解读
  3. python重复import_Python module重复载入的问题
  4. 电脑故障检测软件_有什么软件可以检测出电脑配置是否达到游戏配置。
  5. I春秋——web Write up(三)
  6. Python视频制作工具Manim入门,文本使用详细介绍
  7. 甘肃计算机教室中标,大单纷至沓来 甘肃百亿工程浪潮电脑中标8000台
  8. 计算机网络 --- 网络层IP地址
  9. Centos7 安装docker和docker-compose
  10. 报错,Error in created hook: “SyntaxError: Unexpected token o in JSON at position 1“
  11. 把握新航道,CSDN智能汽车技术路线图正式发布
  12. PHP微信小程序生成带参二维码getwxacodeunlimit
  13. html5头部区域标签,HTML5语义标签(header、section、footer)
  14. android 9.0打开文件管理器,安卓 通过intent调用系统文件管理器打开指定路径目录...
  15. 【LSTM分类】基于双向长短时记忆(BiLSTM)实现数据分类含Matlab源码
  16. Bitly:构建月处理60亿点击的分布式系统
  17. AVI音视频封装格式学习(三)——AVI 数据结构解析
  18. 报错:HTTP/2 stream 1 was not closed cleanly before end of the underlying stream
  19. Google 百度 图标收藏(二)
  20. Kafka单机部署学习演示案例

热门文章

  1. windows7下nbsp;php+mysql+apache+phpm…
  2. libreOffice doc 转pdf
  3. [分享]云时代来了!给大家分享一个山寨版的air disk解决方案【简单,但不完美】
  4. 实战项目(5) MCP9600热电偶检测物体温度
  5. linux 磁盘并发io,Linux系统 磁盘IO过高排查总结
  6. 安卓安装github官方app
  7. asp.net学习流程(应该怎样学习asp.net)
  8. 上班族做什么副业好?深度分析
  9. laravel excel 导出乱码
  10. DxLib 下载页,简单翻译(我不懂日文,瞎编的)