题目描述

$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$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct rec
{int nxt;int to;int w;
}e[2222222];
int head[300000],cnt;
int n,m;
char ch[600];
int st,ed;
bool Map[600][600];
int bs[600][600],u[600][600],d[600][600],l[600][600],r[600][600];
bool vis[300000];
int dis[300000];
queue<pair<int,int> > que;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
void add(int x,int y,int w)
{e[++cnt].nxt=head[x];e[cnt].to=y;e[cnt].w=w;head[x]=cnt;
}
void insert(int x,int y,int w)
{if(Map[x][y]&&!bs[x][y]){bs[x][y]=w;que.push(make_pair(x,y));}
}
void pre_bfs()
{while(!que.empty()){pair<int,int> flag=que.front();que.pop();insert(flag.first-1,flag.second,bs[flag.first][flag.second]+1);insert(flag.first,flag.second-1,bs[flag.first][flag.second]+1);insert(flag.first+1,flag.second,bs[flag.first][flag.second]+1);insert(flag.first,flag.second+1,bs[flag.first][flag.second]+1);}
}
void pre_work()
{for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(Map[i][j]){if(!Map[i][j-1])l[i][j]=(i-1)*m+j;else l[i][j]=l[i][j-1];if(!Map[i-1][j])u[i][j]=(i-1)*m+j;else u[i][j]=u[i-1][j];}for(int i=n;i;i--)for(int j=m;j;j--)if(Map[i][j]){if(!Map[i][j+1])r[i][j]=(i-1)*m+j;else r[i][j]=r[i][j+1];if(!Map[i+1][j])d[i][j]=(i-1)*m+j;else d[i][j]=d[i+1][j];}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(Map[i][j]){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);}if(Map[i+1][j]){add((i-1)*m+j,i*m+j,1);add(i*m+j,(i-1)*m+j,1);}if(u[i][j]!=(i-1)*m+j)add((i-1)*m+j,u[i][j],bs[i][j]);if(d[i][j]!=(i-1)*m+j)add((i-1)*m+j,d[i][j],bs[i][j]);if(l[i][j]!=(i-1)*m+j)add((i-1)*m+j,l[i][j],bs[i][j]);if(r[i][j]!=(i-1)*m+j)add((i-1)*m+j,r[i][j],bs[i][j]);}
}
void Dij(int x)
{memset(dis,0x3f,sizeof(dis));q.push(make_pair(0,x));dis[x]=0;while(!q.empty()){int flag=q.top().second;q.pop();if(vis[flag])continue;vis[flag]=1;for(int i=head[flag];i;i=e[i].nxt)if(dis[e[i].to]>dis[flag]+e[i].w){dis[e[i].to]=dis[flag]+e[i].w;q.push(make_pair(dis[e[i].to],e[i].to));}}
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",ch+1);for(int j=1;j<=m;j++){if(ch[j]=='C')st=(i-1)*m+j;if(ch[j]=='F')ed=(i-1)*m+j;if(ch[j]=='#')que.push(make_pair(i,j));if(ch[j]=='C'||ch[j]=='F'||ch[j]=='.')Map[i][j]=1;}}pre_bfs();pre_work();Dij(st);printf("%d",dis[ed]);return 0;
}


rp++

转载于:https://www.cnblogs.com/wzc521/p/11320354.html

[CSP-S模拟测试]:走格子(模拟+BFS+Dijkstra)相关推荐

  1. 九校联考-长沙市一中NOIP模拟Day2T2 走格子(cell)

    问题描述 CYJ想找到他的小伙伴FPJ,.CYJ和FPJ现在位于一个房间里,这个房间的布置可以看成一个N行M列的矩阵,矩阵内的每一个元素会是下列情况中的一种: 障碍区域-这里有一堵墙(用'#'表示). ...

  2. NOIP模拟测试14「旋转子段·走格子·柱状图」

    旋转子段 连60分都没想,考试一直肝t3,t2,没想到t1最简单 我一直以为t1很难,看了题解发现也就那样 题解 性质1 一个包含a[i]旋转区间值域范围最多为min(a[i],i)----max(a ...

  3. 2018冬令营模拟测试赛(十八)

    2018冬令营模拟测试赛(十八) [Problem A]Table 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见"试题描述&qu ...

  4. Spring Cloud Alibaba 实战 | 第十二篇: 微服务整合Sentinel的流控、熔断降级,赋能拥有降级功能的Feign新技能熔断,实现熔断降级双剑合璧(JMeter模拟测试)

    文章目录 一. Sentinel概念 1. 什么是Sentinel? 2. Sentinel功能特性 3. Sentinel VS Hystrix 二. Docker部署Sentinel Dashbo ...

  5. 2018冬令营模拟测试赛(九)

    2018冬令营模拟测试赛(九) [Problem A]王子 试题描述 不是所有王子都会遇见自己的中关村,主公,公主. 从前有个王子姓王,王王子遇到了一位美丽的公主,她的名字当然是公公主啦. 王王子对公 ...

  6. Mockito:一个强大的用于Java开发的模拟测试框架

    介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用Mockito的Java示例. 模拟(Mock)的概念 在软件开发的世界之外, "mock"一 ...

  7. WebRTC通话质量调优:三个弱网模拟测试工具的使用与对比

    作为一个使用 WebRTC 独立开发者或团队,怎样才能知道自己 App 的通话质量已经"达标"了呢?如何进行合理的弱网模拟测试?介绍给开发者们三个开源工具的部署.使用方法,及其各自 ...

  8. 存根类 测试代码 java_测试双打:模拟,假人和存根

    存根类 测试代码 java 大多数班级都有合作者. 在进行单元测试时,您通常希望避免使用那些协作者的实际实现方式来避免测试的脆弱性和绑定/耦合,而应使用测试双打:模拟,存根和双打. 本文引用了有关该主 ...

  9. 测试双打:模拟,假人和存根

    大多数班级都有合作者. 在进行单元测试时,您通常希望避免使用那些协作者的实际实现方式来避免测试的脆弱性和绑定/耦合,而应使用测试双打:模拟,存根和双打. 本文引用了有关该主题的两篇现有文章:Marti ...

  10. NOIP模拟测试19「count·dinner·chess」

    反思: 我考得最炸的一次 怎么说呢?简单的两个题0分,稍难(我还不敢说难,肯定又有人喷我)42分 前10分钟看T1,不会,觉得不可做,完全不可做,把它跳了 最后10分钟看T1,发现一个有点用的性质,仍 ...

最新文章

  1. 想爱容易,相处难:当ASP.NET MVC爱上IoC
  2. Scrum之 站立例会
  3. Android自定义顶部栏及侧滑菜单和fragment+viewpag滑动切换的实现
  4. 【PKUSC2018】星际穿越【结论】【倍增dp】
  5. es6新增的html标签,javascript – 如何导入已在html中的标签中定义的es6模块?
  6. mac下常用数据库及nginx笔记
  7. mysql并行dml_MySql的回顾九DML表数据的增,删,改,与DDL库表的增删改,约束
  8. 内嵌网页 UniWebView 3 的使用
  9. Object-C 语法基础
  10. 计算机视觉论文-2021-07-21
  11. 计算机小高考成绩,2018江苏小高考成绩出来了!昆山*亮眼的学校是…
  12. 2007年春节读书心得
  13. [Django ]Django 的数据库操作
  14. 华大单片机HC32L130/HC32L136PWM配置
  15. mysql直方图_MySQL · 特性分析 · 直方图的实现与分析
  16. win怎么查看显示器大小,显示器是多少寸,查看显示器尺寸
  17. 2021前端面试总结及反思
  18. phpstorm2019--设置自动换行
  19. AI入门----深度学习的软硬件配置
  20. 世界上最难的视觉图_【若寒专栏】被喻为世界上最难的联赛——2019赛季日本J2联赛球队总结(7 完结)...

热门文章

  1. C语言虚词怎么在程序里表示,文言虚词用法推断
  2. CTF-WEB小技俩 ——合天网安实验室学习笔记
  3. ultracompare中文乱码解决方法
  4. PPT插入形状,在里面填写文字,文本框过大
  5. 别人是怎么将图片贴在屏幕上的?
  6. 小强开饭店-从单体应用到微服务
  7. isbn书号查询php代码,php根据isbn书号查询amazon网站上的图书信息的示例_PHP
  8. 关于自定View的ViewGroup (嵌套View)
  9. CKEditor5系列二:创建简单插件
  10. python可以做什么灰产-广州市标书资料销毁详细流程