问题描述

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 ,(4 ≤ N,M ≤ 500).表示地图大小。
接下来的N行每行一个长度为M的字符串.表示地形。
输出
你需要输出最少的到达终点的时间,如果不能到达请输出”no”。

样例输入
6 8
########
#.##…F#
#C.##…#
#…#…#
#…##
########

输出样例
4

样例 解释
从C点(3,2)开始,我们首先向左发射传送门,再向下发射传送门,向左进入传送门,到达(5,2),向右发射传送门,向下进入传送门,到达(5,6),向上发射传送门,向右进入传送门,到达(2,6),向右移动,到达F.

数据范围
50%的数据满足:4<= N,M <=15;
100%的数据满足:4<= N,M <=500;
题解:行动可以分为两种:

  1. 步行,花费一个单位的时间移动到4联通的相邻格子中去.
  2. 使用传送门,指定一个方向的墙的前面的一个格子,步行至最近的一个墙的面前,使用传送门传送.花费的时间为到达最近墙面前花费的时间+1.
    两种行动相组合即可组成任意行动过程.那BFS求出最近的墙的距离,预处理上下左右的第一面墙前的格子.然后建图用DJ跑最短路即可.复杂度为O(MNlog(NM))。

code

#include<bits/stdc++.h>using namespace std;int n,m,st,ed,len=0;
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
char s[550][550];
int b[550][550],Left[550][550],Right[550][550],Under[550][550],Above[550][550],vis[511111],d[511111],lin[511111];
struct node{int y,v,nxt;
}e[511111*5];
struct Dijk{int v,x;bool operator <(const Dijk &a) const{return a.v < v;}
};inline int num(int i,int j) {return (i-1)*m+j;}queue<pair<int,int> >q;
void bfs()
{   while(q.size()){int x=q.front().first,y=q.front().second; q.pop();    for(int i=0;i<4;i++){int tox=x+dx[i],toy=y+dy[i];if(s[tox][toy]=='.' && !b[tox][toy]){b[tox][toy]=b[x][y]+1;q.push(make_pair(tox,toy));     }}}
} void pre()
{for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){if(s[i][j]=='#') continue;   if(s[i-1][j]=='#') Above[i][j]=num(i,j);else Above[i][j]=Above[i-1][j];if(s[i][j-1]=='#') Left[i][j]=num(i,j);else Left[i][j]=Left[i][j-1];}    for(int i=n;i>=1;i--)for(int j=m;j>=1;j--){if(s[i][j]=='#') continue;     if(s[i+1][j]=='#') Under[i][j]=num(i,j);else Under[i][j]=Under[i+1][j];if(s[i][j+1]=='#') Right[i][j]=num(i,j);else Right[i][j]=Right[i][j+1];      }
}void ins(int x,int y,int v) { e[++len].nxt=lin[x]; lin[x]=len; e[len].y=y; e[len].v=v; }
void make_node()
{for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)   {if(s[i][j]=='#') continue;if(s[i+1][j]=='.')  ins(num(i,j),num(i+1,j),1),ins(num(i+1,j),num(i,j),1);if(s[i][j+1]=='.')  ins(num(i,j),num(i,j+1),1),ins(num(i,j+1),num(i,j),1);if(Left[i][j]!=num(i,j))  ins(num(i,j),Left[i][j],b[i][j]);if(Right[i][j]!=num(i,j)) ins(num(i,j),Right[i][j],b[i][j]);if(Under[i][j]!=num(i,j)) ins(num(i,j),Under[i][j],b[i][j]);if(Above[i][j]!=num(i,j)) ins(num(i,j),Above[i][j],b[i][j]);    }
} priority_queue<Dijk> qe;
void Dijsktra()
{qe.push((Dijk){0,st}); d[st]=0;while(qe.size()){int x=qe.top().x,v=qe.top().v; qe.pop();if(vis[x]) continue; vis[x]=1;for(int i=lin[x];i;i=e[i].nxt){int y=e[i].y;  if(v+e[i].v<d[y]) d[y]=v+e[i].v,qe.push((Dijk){d[y],y});}}
}
int main()
{freopen("cell.in","r",stdin);freopen("cell.out","w",stdout);cin>>n>>m;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){cin>>s[i][j];if(s[i][j]=='C') st=num(i,j),s[i][j]='.';if(s[i][j]=='F') ed=num(i,j),s[i][j]='.';if(s[i][j]=='#') q.push(make_pair(i,j));}  bfs();pre();make_node();memset(d,10,sizeof(d));Dijsktra();if(d[ed]==168430090) cout<<"no";else cout<<d[ed];return 0;
}

hl uoj1841 走格子相关推荐

  1. 【51NOD】1486 大大走格子

    [算法]动态规划+组合数学 [题意]有一个h行w列的棋盘,定义一些格子为不能走的黑点,现在要求从左上角走到右下角的方案数. [题解] 大概能考虑到离散化黑点后,中间的空格子直接用组合数计算. 然后解决 ...

  2. 51nod 1344 走格子【贪心/前缀和】

    1344 走格子 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题  收藏  关注 有编号1-n的n个格子,机器人从1号格子顺序向后走,一直走到n号格子,并需要从n号格 ...

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

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

  4. 【有趣的Python小程序】Python多个简单上手的库制作WalkLattice 走格子游戏 (思路篇)上

    篇写上一个思路篇,那么今天我们就来完成这一项工作 源代码和配套文件 链接: https://caiyun.139.com/m/i?135ClY1yWrSKX 提取码:e4pq 复制内容打开中国移动云盘 ...

  5. 1344 走格子 (前缀和)

    有编号1-n的n个格子,机器人从1号格子顺序向后走,一直走到n号格子,并需要从n号格子走出去.机器人有一个初始能量,每个格子对应一个整数A[i],表示这个格子的能量值.如果A[i] > 0,机器 ...

  6. Wannafly挑战赛17 - 走格子(模拟)

    题目链接 题目描述 在平面上有n*n大小的正方形,定义正方形左下角坐标是(1,1),右下角坐标是(n,1) 现在A君在左下角,他的初始方向是向右,他要在正方形内走m步 当A君碰到边界或者已经走过的格子 ...

  7. 201301 JAVA2~3级---走格子

    请编写一个函数(允许增加子函数),计算n x m的棋盘格子(n为横向的格子数,m为竖向的格子数)沿着各自边缘线从左上角走到右下角,总共有多少种走法,要求不能走回头路,即:只能往右和往下走,不能往左和往 ...

  8. 【51Nod - 1344】走格子 (思维)

    题干: 有编号1-n的n个格子,机器人从1号格子顺序向后走,一直走到n号格子,并需要从n号格子走出去.机器人有一个初始能量,每个格子对应一个整数Aii,表示这个格子的能量值.如果Aii > 0, ...

  9. 【有趣的Python小程序】Python多个简单上手的库制作WalkLattice 走格子游戏 (思路篇)下

    在上一篇的分析当中,我们已经基本上完成了基本模块的代码,接下来,我们就为这个代码增添更多好玩有趣的小功能吧.那么还没有看过代码篇和思路篇的朋友们可以点击下方链接直接跳转到代码篇去的哈 源代码和配套文件 ...

  10. 走格子(数学组合/动态规划)

    一个高中就学过的问题:现有一个m * n的网格,从最左上角出发,每次只能向右或者向下移动一格,问有多少种不同的方法可以到达最右下角的格子? 可以用高中学过的排列组合来解,见下图一个6*6的格子,从A走 ...

最新文章

  1. 普渡大学计算机硕士申请条件,普渡大学计算机与信息技术理学硕士研究生申请要求及申请材料要求清单...
  2. 互联网老师论坛高调炫耀收入:硕士毕业三年,月入九万多!
  3. MicroPython实例之TPYBoardv102自动浇花系统
  4. Hibernate组件(Component)映射
  5. dubbo配置(一)
  6. C语言面向对象编程(五):单链表实现
  7. Visual Studio 2017将于3月7日发布
  8. qq纵横四海源码_【0基础】纵横中文网python爬虫实战
  9. python png 背景透明_python – Pygame:在png图像中将所有白色像素转换为完全透明...
  10. 【虹科免费直播预告】光电技术直播月重磅来袭!
  11. hencoder学习自定义view(1)
  12. 用Python实现双色球随机选号
  13. NumPy.npy与pandas DataFrame
  14. 用python爬取网易云音乐评论
  15. H5拖拽地址-高德地图VUE版
  16. 广电网络电视怎么服务器连接中断,怎么解决广电网络看电视卡
  17. Three.js OBJ模型的剖切
  18. android media的文件类型,NOMEDIA 文件扩展名: 它是什么以及如何打开它?
  19. 瓷介电容知多少(一)导电胶粘接片式瓷介电容器的探讨
  20. Centos7单机安装torque6.1.2

热门文章

  1. 股市基础知识、主力战法【一】
  2. 计算机键盘卡扣原理,笔记本键盘怎么拆?笔记本键盘卡扣、排线如何打开?
  3. 电脑“减负”必备,分享一款优秀的重复文件查找工具
  4. Substance Designer Dirt Ground
  5. 整理2005年至2019年东盟10国GDP数据
  6. linux tf卡格式,一点点福利,把TF卡格式成NTFS格式,结果。。。。顺便问下大家的TF卡用什么格式?...
  7. 【C++】C++ 内存分配(new,operator new)详解
  8. 解决-系统策略禁止安装此设备,请与系统管理员联系
  9. c语言写流水灯程序,用汇编和C语言 写流水灯程序
  10. C++排列组合及应用