题目描述

$CYJ$想找到他的小伙伴$FPJ$,$CYJ$和$FPJ$现在位于一个房间里,这个房间的布置可以看成一个$N$行$M$列的矩阵,矩阵内的每一个元素会是下列情况中的一种:
$1.$障碍区域—这里有一堵墙(用$'\#'$表示)。
$2.$这是$CYJ$最开始在的区域(用$'C'$表示)。
$3.$这是$FPJ$在的区域(用$'F'$表示)。
$4.$空区域(用$'.'$表示)。
$CYJ$携带了一个所谓传送枪的东西,这是一把可以创造传送门的枪械,在每一次行动中,他可以选择下列操作中的一项:
$1.$移向一个相邻的格子中(上,下,左,右,不能移到墙在的格子里)。这个操作要消耗一个单位的时间。
$2.$转向一个墙(不需要相邻,只需面向即可),向其发射传送门,传送门会留在墙内面向你的地方(至多只能同时存在两扇传送门),若墙上已经有两扇传送门,而你发射了第三扇,那么最初发射的那一扇会消失。同时,你无法在一个位置制造两扇传送门(这个操作不会耗费时间)。
$3.$如果他与一块墙壁相邻且面前有一扇传送门,那么他可以移动到另一扇传送门前方的格子。这个操作会耗费一个单位的时间。
$CYJ$想要知道自己最少需要多少时间才能够从起点($'C'$)到达终点($'F'$)。
请注意:我们保证地图边缘会是一圈墙壁且一定存在$'C'$,$'F'$。


输入格式

第一行输入两个正整数$N$和$M$,表示地图大小。
接下来的$N$行每行一个长度为$M$的字符串,表示地形。


输出格式

你需要输出最少的到达终点的时间,如果不能到达请输出$"no"$。


样例

样例输入1:

4 4
####
#.F#
#C.#
####

样例输出1:

2

样例输入2:

6 8
########
#.##..F#
#C.##..#
#..#...#
#.....##
########

样例输入2:

4

样例输入3:

4 5
#####
#C#.#
###F#
#####

样例输出3:

no


数据范围与提示

$50\%$的数据满足:$4\leqslant N,M\leqslant 15$;
$100\%$的数据满足:$4\leqslant N,M\leqslant 500$;


题解

这道题教练出的有些尴尬,我在个人简介中说过我在多个信竞队都混过,然后就有了这道题的故事。

大概在半年前,$Akoasm$大神出了这道题,他想卖版权,我帮他审的这道题,然而就在半年后……

顺便附一个$Akoasm$大神的链接:$\mathfrak{Akoasm}$

扯淡完了,言归正转。

这道题应该是我审过的$Akoasm$大神出的最好的一道题了。

题目很新颖,很难想到正解,好多人都想到的是爆搜+剪枝,至于少数几个人想到了正解。

首先,我们通过$BFS$预处理出距离最近墙的距离,在预处理出上下左右的第一面墙前的格子在哪里,建图,在图上跑$Dijkstra$即可。

就这么简单,主要是很难想得到。

时间复杂度:$\Theta(n\times m\log(n\times m))$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct rec
  4. {
  5. int nxt;
  6. int to;
  7. int w;
  8. }e[2222222];
  9. int head[300000],cnt;
  10. int n,m;
  11. char ch[600];
  12. int st,ed;
  13. bool Map[600][600];
  14. int bs[600][600],u[600][600],d[600][600],l[600][600],r[600][600];
  15. bool vis[300000];
  16. int dis[300000];
  17. queue<pair<int,int> > que;
  18. priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
  19. void add(int x,int y,int w)
  20. {
  21. e[++cnt].nxt=head[x];
  22. e[cnt].to=y;
  23. e[cnt].w=w;
  24. head[x]=cnt;
  25. }
  26. void insert(int x,int y,int w)
  27. {
  28. if(Map[x][y]&&!bs[x][y])
  29. {
  30. bs[x][y]=w;
  31. que.push(make_pair(x,y));
  32. }
  33. }
  34. void pre_bfs()
  35. {
  36. while(!que.empty())
  37. {
  38. pair<int,int> flag=que.front();
  39. que.pop();
  40. insert(flag.first-1,flag.second,bs[flag.first][flag.second]+1);
  41. insert(flag.first,flag.second-1,bs[flag.first][flag.second]+1);
  42. insert(flag.first+1,flag.second,bs[flag.first][flag.second]+1);
  43. insert(flag.first,flag.second+1,bs[flag.first][flag.second]+1);
  44. }
  45. }
  46. void pre_work()
  47. {
  48. for(int i=1;i<=n;i++)
  49. for(int j=1;j<=m;j++)
  50. if(Map[i][j])
  51. {
  52. if(!Map[i][j-1])l[i][j]=(i-1)*m+j;
  53. else l[i][j]=l[i][j-1];
  54. if(!Map[i-1][j])u[i][j]=(i-1)*m+j;
  55. else u[i][j]=u[i-1][j];
  56. }
  57. for(int i=n;i;i--)
  58. for(int j=m;j;j--)
  59. if(Map[i][j])
  60. {
  61. if(!Map[i][j+1])r[i][j]=(i-1)*m+j;
  62. else r[i][j]=r[i][j+1];
  63. if(!Map[i+1][j])d[i][j]=(i-1)*m+j;
  64. else d[i][j]=d[i+1][j];
  65. }
  66. for(int i=1;i<=n;i++)
  67. for(int j=1;j<=m;j++)
  68. if(Map[i][j])
  69. {
  70. if(Map[i][j+1]){add((i-1)*m+j,(i-1)*m+j+1,1);add((i-1)*m+j+1,(i-1)*m+j,1);}
  71. if(Map[i+1][j]){add((i-1)*m+j,i*m+j,1);add(i*m+j,(i-1)*m+j,1);}
  72. if(u[i][j]!=(i-1)*m+j)add((i-1)*m+j,u[i][j],bs[i][j]);
  73. if(d[i][j]!=(i-1)*m+j)add((i-1)*m+j,d[i][j],bs[i][j]);
  74. if(l[i][j]!=(i-1)*m+j)add((i-1)*m+j,l[i][j],bs[i][j]);
  75. if(r[i][j]!=(i-1)*m+j)add((i-1)*m+j,r[i][j],bs[i][j]);
  76. }
  77. }
  78. void Dij(int x)
  79. {
  80. memset(dis,0x3f,sizeof(dis));
  81. q.push(make_pair(0,x));
  82. dis[x]=0;
  83. while(!q.empty())
  84. {
  85. int flag=q.top().second;
  86. q.pop();
  87. if(vis[flag])continue;
  88. vis[flag]=1;
  89. for(int i=head[flag];i;i=e[i].nxt)
  90. if(dis[e[i].to]>dis[flag]+e[i].w)
  91. {
  92. dis[e[i].to]=dis[flag]+e[i].w;
  93. q.push(make_pair(dis[e[i].to],e[i].to));
  94. }
  95. }
  96. }
  97. int main()
  98. {
  99. scanf("%d%d",&n,&m);
  100. for(int i=1;i<=n;i++)
  101. {
  102. scanf("%s",ch+1);
  103. for(int j=1;j<=m;j++)
  104. {
  105. if(ch[j]=='C')st=(i-1)*m+j;
  106. if(ch[j]=='F')ed=(i-1)*m+j;
  107. if(ch[j]=='#')que.push(make_pair(i,j));
  108. if(ch[j]=='C'||ch[j]=='F'||ch[j]=='.')Map[i][j]=1;
  109. }
  110. }
  111. pre_bfs();
  112. pre_work();
  113. Dij(st);
  114. printf("%d",dis[ed]);
  115. return 0;
  116. }

rp++

[CSP-S模拟测试]:走格子(模拟+BFS+Dijkstra)的更多相关文章

  1. [CSP-S模拟测试]:跳房子(模拟)

    题目描述 跳房子,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一.跳房子是在$N$个格子上进行的,$CYJ$对游戏进行了改进,该成了跳棋盘,改进后的游戏是在一个$N$行$M$列的棋盘上进行,并 ...

  2. [CSP-S模拟测试]:砖块(模拟)

    题目描述 在一个二维网格平面上,一个网格的坐标由其左下角的点的坐标定义$(x,y)$.在一个二维网格平面上,一个网格的坐标由其左下角的个点的坐标定义$(0,0)$的区域中,此时存在高度为$k$的初始砖 ...

  3. [考试反思]0719NOIP模拟测试6 + 0722NOIP模拟测试7

    连续爆炸,颇为愉快. 第6次:Rank #4 第7次:Rank #9 对于第6次考试,个人比较满意,因为T1只是差了一个卡常. 因为在考试前两天刚讲了矩阵,满脑子都是矩阵,还想到了循环矩阵优化. 整个 ...

  4. [CSP-S模拟测试]:666(模拟)

    题目描述 不忘初心. 小$\pi$假期在家无聊,打开了某弹幕直播网站. 突然,有一个精彩的镜头. 小$\pi$看到了满屏的$6$,其中,有$666$.也有$666666$.也有$6666666666. ...

  5. [CSP-S模拟测试]:Reverse(模拟+暴力+剪枝)

    题目描述 小$G$有一个长度为$n$的$01$串$T$,其中只有$T_S=1$,其余位置都是$0$.现在小$G$可以进行若干次以下操作: $\bullet$选择一个长度为K的连续子串($K$是给定的常 ...

  6. csp-s模拟测试112 & csp-s模拟测试113

    考前两天模拟. Day1直接炸飞,T1浪费的时间太长,对拍+调试了一个多小时但复杂度还不能过,最后5分钟想出来了解决方案但是已经打不出来了.T2读入出了事故RE0.T3打了假贪心. Day2心态几乎也 ...

  7. [CSP-S模拟测试]:五子棋(模拟)

    题目传送门(内部题122) 输入格式 输入文件第一行为一个正整数$n$,表示双方总共下了多少步棋. 接下来$n$行,输入文件每行两个正整数.第$i$行的两个数$x,y$表示第$i$步的棋子下在了第$x ...

  8. [CSP-S模拟测试]:线性代数(模拟)

    题目传送门(内部题113) 输入格式 第一行一个正整数$n$. 接下来$n$行,每行$n$个整数,描述$C$矩阵.保证输入的是一个林先森矩阵. 输出格式 若不可能实现,则输出一行$Impossible ...

  9. [CSP-S模拟测试]:集合论(模拟)

    题目传送门(内部题73) 输入格式 输入文件$jihe.in$ 第一行一个整数$m$,表示操作的次数. 接下来$m$行,每行描述一个操作. 每行的开始都是一个数字,$1,2,3,4$依次代表$unio ...

随机推荐

  1. 抓取某高校附近共享单车位置,并使用web方式展示过去几天的位置变化

    效果如图 使用了高德地图API:https://lbs.amap.com/api/javascript-api/example/marker/massmarks js代码如下: function Ma ...

  2. javascript中json字符串对象转化

    li = [1,2,3,4] s = JSON.stringify(li)  ---转化为字符串 JSON.parse(s) --转化为对象

  3. IDEA-包层级结构显示(三)

    IntelliJ IDEA包层级结构显示 如:A.B.C,在项目中希望以如下形式显示: A B C 效果: 再更换为A.B.C形式显示

  4. Log4net使用(二)

    转:http://www.cnblogs.com/basilwang/archive/2006/06/09/421868.html Log4net同时按照日期和大小生成RollingFile和访问Sy ...

  5. 知识点C++

    比较2个字符串的大小…… s1=s2,strcmp(s1,s2) == ; s1>s2, strcmp(s1,s2) == ; s1<s2, strcmp(s1,s2) == -; str ...

  6. Spring Cloud部署+Mybatis整合

    一:架构简介 Spring Cloud是微服务思想的体现.每个项目单独部署,我只需要知道你服务的name就能直接调用你,而不关心你的ip和端口的变化.当接口服务不可用的时候,我能感知到你无法用了,就不 ...

  7. docker添加加速器

    通过 Docker 官方镜像加速,中国区用户能够快速访问最流行的 Docker 镜像.该镜像托管于中国大陆,本地用户现在将会享受到更快的下载速度和更强的稳定性,从而能够更敏捷地开发和交付 Docker ...

  8. 小白学Python(9)——pyecharts 绘制漏斗图 Funnel

    根据pyecharts的介绍一直没有研究明白def和return的用法,无法显示完整的漏斗图,还请各位指点. 根据上文绘制bar的方法,我更改了代码,做出了漏斗图,不过和demo不一样,而且数据也会随 ...

  9. D Makoto and a Blackboard

    Makoto and a Blackboard time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  10. 可下拉的PinnedHeaderExpandableListView的实现

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/singwhatiwanna/article/details/25546871 转载请注明出处:htt ...