问题描述

CYJ想找到他的小伙伴FPJ,.CYJ和FPJ现在位于一个房间里,这个房间的布置可以看成一个N行M列的矩阵,矩阵内的每一个元素会是下列情况中的一种:

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

输入

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

输出

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

先BFS搜出每个点到墙(或到旁边有墙的点)的距离,同时用这个距离建图,建完图跑diji或spfa得出正解

#include<bits/stdc++.h>
using namespace std;const int Maxn = 505;
const int MX = 3e5+5;
const int inf = 1e9;int N,M,S,T,cnt;
int md[Maxn][Maxn],Lm[Maxn][Maxn],Rm[Maxn][Maxn];
int Dm[Maxn][Maxn],Um[Maxn][Maxn],hed[MX];
int nxt[MX<<4],to[MX<<4],len[MX<<4],dis[MX];
char mp[Maxn][Maxn];
struct  data{int x , y;bool operator <(const data &A) const{return y > A.y;}
};queue<data>Q;inline int id(int x,int y){return (x - 1)*M + y;}void inc(int x,int y,int d){if(mp[x][y] == '.' && !md[x][y])md[x][y] = d , Q.push((data){x,y});
}void Bfs(){while(!Q.empty()){int x = Q.front().x,y = Q.front().y;Q.pop();inc(x - 1 , y , md[x][y] + 1);inc(x , y - 1 , md[x][y] + 1);inc(x + 1 , y , md[x][y] + 1);inc(x , y + 1 , md[x][y] + 1); }
}void Adg(int x,int y,int l){nxt[++cnt] = hed[x]; to[cnt] = y; hed[x] = cnt; len[cnt] = l;
}void Addedge(int x,int y,int l){Adg(x , y , l); Adg(y , x , l);
}void init(){for(int i = 1 ; i <= N ; ++i)for(int j = 1 ; j <= M ; ++j) if(mp[i][j] == '.'){if(mp[i][j-1] == '#') Lm[i][j] = id(i , j);else Lm[i][j] = Lm[i][j - 1];if(mp[i-1][j] == '#') Um[i][j] = id(i , j);else Um[i][j] = Um[i - 1][j]; } for(int i = N ; i ; --i)for(int j = M ; j ; --j) if(mp[i][j] == '.'){if(mp[i][j+1] == '#') Rm[i][j] = id(i,j);else Rm[i][j] = Rm[i][j + 1];if(mp[i+1][j] == '#') Dm[i][j] = id(i,j);else Dm[i][j] = Dm[i + 1][j]; }
}void Build(){for(int i = 1 ; i <= N ; ++i)for(int j = 1 ; j <= M ; ++j) if(mp[i][j] == '.'){if(mp[i][j + 1] == '.') Addedge(id(i,j),id(i,j+1),1);if(mp[i + 1][j] == '.') Addedge(id(i,j),id(i+1,j),1);if(Lm[i][j] != id(i , j)) Adg(id(i,j),Lm[i][j],md[i][j]);if(Rm[i][j] != id(i , j)) Adg(id(i,j),Rm[i][j],md[i][j]);if(Um[i][j] != id(i , j)) Adg(id(i,j),Um[i][j],md[i][j]);if(Dm[i][j] != id(i , j)) Adg(id(i,j),Dm[i][j],md[i][j]);  }
}void Dijkstra(){priority_queue<data>PQ;for(int i = 1 ; i <= N*M ; ++i)dis[i] = inf; dis[S] = 0; PQ.push((data){S,dis[S]});while(!PQ.empty()){int x = PQ.top().x,L = PQ.top().y;PQ.pop();if(L > dis[x]) continue;for(int i = hed[x],v ; i ; i = nxt[i])if(dis[v = to[i]] > dis[x] + len[i]){//if(v == T) printf("%d\n",x);dis[v] = dis[x] + len[i];PQ.push((data){v,dis[v]}); }}
}int main(){freopen("cell.in","r",stdin);freopen("cell.out","w",stdout);scanf("%d%d",&N,&M);for(int i = 1 ; i <= N ; ++i)scanf("%s" , mp[i] + 1);for(int i = 1 ; i <= N ; ++i)for(int j = 1 ; j <= M ; ++j){if(mp[i][j] == 'C') mp[i][j] = '.',S = id(i,j);if(mp[i][j] == 'F') mp[i][j] = '.',T = id(i,j);}for(int i = 1 ; i <= N ; ++i)for(int j = 1 ; j <= M ; ++j)if(mp[i][j] == '#') Q.push((data){i,j});Bfs(); init(); Build(); Dijkstra();if(dis[T] != inf) printf("%d\n",dis[T]);else printf("no\n");return 0;
}

转载于:https://www.cnblogs.com/shulker/p/9663138.html

九校联考-长沙市一中NOIP模拟Day2T2 走格子(cell)相关推荐

  1. 九校联考-长沙市一中NOIP模拟Day1T1 矩阵游戏(game)

    问题描述 LZK发明一个矩阵游戏,大家一起来玩玩吧,有一个N行M列的矩阵.第一行的数字是1,2,-M,第二行的数字是M+1,M+2-2M,以此类推,第N行的数字是(N-1)M+1,(N-1)M+2-N ...

  2. 九校联考-长沙市一中NOIP模拟Day2T1 旋转子段(rotate)

    问题描述 ZYL有N张牌编号分别为1, 2,--,N.他把这N张牌打乱排成一排,然后他要做一次旋转使得旋转后固定点尽可能多.如果第i个位置的牌的编号为i,我们就称之为固定点. 旋转可以被认为是将其中的 ...

  3. 九校联考-长沙市一中NOIP模拟Day1T3 优美序列(sequence)

    问题描述 Lxy养了N头奶牛,他把N头奶牛用1..N编号,第i头奶牛编号为i.为了让奶牛多产奶,每天早上他都会让奶牛们排成一排做早操.奶牛们是随机排列的.在奶牛排列中,如果一段区间[L,R]中的数从小 ...

  4. 九校联考-长沙市一中NOIP模拟Day2T3 柱状图(column)

    问题描述 WTH 获得了一个柱状图 , 这个柱状图一共有 N 个柱子 , 最开始第 i 根柱子的高度为 x i , 他现在要将这个柱状图排成一个屋顶的形状 , 屋顶的定义如下 : 屋顶存在一个最高的柱 ...

  5. 九校联考-DL24 凉心模拟 Day1T3 三米诺 (tromino)

    题目描述 金企鹅同学非常擅长用 1×21×21×2 的多米诺骨牌覆盖棋盘的题.有一天,正在背四六级单词的他忽然想:既然两个格子的积木叫"多米诺 (domino)",那么三个格子的的 ...

  6. 九校联考-DL24凉心模拟Day1T3 三米诺 (tromino)

    题目背景 金企鹅同学非常擅长用1*2的多米诺骨牌覆盖棋盘的题.有一天,正 在背四六级单词的他忽然想:既然两个格子的积木叫"多米诺(domino)",那 么三个格子的的积木一定叫&q ...

  7. 九校联考-DL24凉心模拟Day2T1 锻造(forging)

    1.1 题目背景 勇者虽然武力值很高,但在经历了多次战斗后,发现怪物越来越难打 于是开始思考是不是自己平时锻炼没到位,于是苦练一个月后发现......自己连一个史莱姆都打不过了. 勇者的精灵路由器告诉 ...

  8. 【九校联考-24凉心模拟】锻造(forging)

    题目背景 勇者虽然武力值很高,但在经历了多次战斗后,发现怪物越来越难打, 于是开始思考是不是自己平时锻炼没到位,于是苦练一个月后发现--自 己连一个史莱姆都打不过了. 勇者的精灵路由器告诉勇者其实是他 ...

  9. 九校联考-DL24 凉心模拟 Day2T1 锻造 (forging)

    题目描述 勇者虽然武力值很高,但在经历了多次战斗后,发现怪物越来越难打,于是开始思考是不是自己平时锻炼没到位,于是苦练一个月后发现--自己连一个史莱姆都打不过了. 勇者的精灵路由器告诉勇者其实是他自己 ...

最新文章

  1. MySQL-WorkBench修改MySQL配置注意事项
  2. BZOJ3559 : [Ctsc2014]图的分割
  3. (Unfinished)RNN-循环神经网络之LSTM和GRU-04介绍及推导
  4. Android中attrs.xml文件的使用详解
  5. Ubuntu18.04配置视觉SLAM十四讲代码运行环境
  6. EDA365_skill2.5百度网盘资源
  7. SPSS学习笔记(一)判断是否服从正态分布
  8. 飞机精确定位模型matlab,一种精确定位飞机位置的方法与流程
  9. shell 中 if[X$1 = X];then 什么意思
  10. Stochastic Weight Averaging
  11. 读书笔记:《群论彩图版》
  12. C++中空类占一字节原因详解
  13. android 内部sdcard出错处理errors=remount-ro改为errors=continue
  14. 【推荐算法论文阅读】BERT4Rec: Sequential Recommendation with Bidirectional Encoder Representations from Trans
  15. python 实现计时器(不同实现方式)
  16. Unity模型导入相关知识
  17. AcWing 168 生日蛋糕【DFS 剪枝 ☆】
  18. NAT端口的映射两种方法
  19. QQlive的缓存提取器
  20. 【VUE 笔记】基础内容

热门文章

  1. 什么是Tick 数据?
  2. 【LeetCode】163.Missing Ranges(Medium)(带锁题)解题报告
  3. Intellij IDEA File Cache Conflict
  4. mysql上年年末_查询年初,年末,去年年初,明年年初与年末sql语句
  5. Docker迁移备份武林秘籍
  6. android 苹果 换机,苹果12怎么一键换机安卓?iPhone12一键换机功能操作步骤
  7. L1-7 谷歌的招聘
  8. Python爬虫Scrapy轮子工具
  9. c语言左值中有运算符,C语言左值,运算符的优先级以及结合性探讨
  10. 极路由X(C526A)刷Openwrt 18.06固件(2021-12-12亲测)