Have Lunch Together
来源:互联网 发布:movielens数据集下载 编辑:程序博客网 时间:2024/06/08 13:30
题意分析
给定一幅字符表示的地图,其中包含有 1 个起点'H'
,若干个座位'S'
,墙壁'#'
和行人'P'
。
其中墙壁'#'
和行人'P'
是不可通过的区域。
假设在地图中,只能沿着上下左右移动,且每移动一个单元格为 1 步。
询问从'H'
点出发,是否能够到达两个相邻的'S'
,且需要移动的步数最少是多少。
算法分析
从题目当中,我们就可以知道本题需要做什么:
读取字符地图,并找到起点的位置。
从起点开始,遍历该地图,记录到达每一个
'S'
的距离。判断是否有两个相邻的
'S'
都可达,若存在多个解,则需要找到最小的值。
那么我们就按照这三个步骤来解决这道题目。
首先是数据的读入,由于输入数据中已经明确的告诉了我们地图为 N 行 M 列,所以我们只需要一行一行读入字符串,并使用char map[N][M]
保存该地图。
map[i][j]
表示原地图的第i
行第j
列的信息。
之后再对整个map[i][j]
进行一次 O(mn) 的遍历,找出起点的位置,并记录下来。
我们用startX
, startY
来记录起点的坐标。
startX = startY = 0;// 读入地图for (int i = 1; i <= N; i++) scanf("%s", map[i] + 1);// 查找起点Hfor (int i = 1; i <= N; i++) for (int j = 1; j <= M; ++j) if (map[i][j] == 'H') { startX = i, startY = j; break; }
第二步,寻找从起点(startX, startY)
分别到每个'S'
的最短路径。这一步我们直接使用BFS
对整个图进行一次遍历。
首先建立数组int step[N][M]
,step[i][j]
表示从起点到(i,j)
的最少步数。
初始化为step[i][j] = INT_MAX
,默认为任何点都无法到达。
开始遍历时,将step[ startX ][ startY ]
设定为0
,并以(startX, startY)
开始BFS
整个地图。
在遍历整个地图的过程中我们需要注意:
当
map[i][j] = '#'
或map[i][j] = 'P'
时,step[i][j]
直接等于INT_MAX
,并且不扩展新的节点。当
map[i][j] = 'S'
时,我们需要更新当前节点的step[i][j]
信息,但是由于当小Hi和小Ho走到位置后就不会再进行移动,所以也不扩展新的节点。
最后当没有新的节点可以到达时,退出BFS
,得到整个地图的step[N][M]
。
bool inMap(int x, int y) { // 在地图内 && 不为墙壁同时也不为行人 return (1 <= x && x <= N && 1 <= y && y <= M) && (map[x][y] == '.' || map[x][y] == 'S');}const int dir[4][2] = { {0, -1}, {1, 0}, {0, 1}, {-1, 0} }; // 方向数组vector< pair<int, int> > seq; // 用一个vector来存储BFS的队列void BFS(int startX, int startY) { // 将起点存入队列 step[ startX ][ startY ] = 0; seq.push_back( make_pair(startX, startY) ); int i = 0; while (i < (int) seq.size()) { for (int dr = 0; dr < 4; ++dr) { // 扩展新的节点 int tempX = seq[i].first + dir[dr][0]; int tempY = seq[i].second + dir[dr][1]; if (inMap(tempX, tempY) && step[tempX][tempY] == INT_MAX) { step[tempX][tempY] = step[ seq[i].first ][ seq[i].second ] + 1; // 当发现是座位时,不再进行扩展 if (map[tempX][tempY] != 'S') seq.push_back( make_pair(tempX, tempY) ); } } ++i; } return ;}
最后一步判断是否有两个连续的'S'
都可达。
此时我们仍然遍历整个地图,因为只是检查是否有相邻的'S'
,不需要考虑顺序,所以我们按照i = 1..n, j = 1..m
的顺序就可以。
当我们扫描到一个'S'
时,首先判定其周围是否还有其他'S'
。由于对称性,我们只需要检查两个方向即可。
若存在,则表示这两个'S'
相邻,此时我们检查这两个位置的step
值。
如果两个位置的step
值都不等于INT_MAX
,则说明这两个位置都是可以到达的。我们根据这两个位置的step
和更新最优解。
当遍历完整个地图后,也就找到了我们所需要寻找的最优值。
int ret = INT_MAX;for (int i = 1; i <= N; ++i) for (int j = 1; j <= M; ++j) // 当前位置为S,且可以到达 if (map[i][j] == 'S' && step[i][j] != 0) { // 检查下边是否有相邻S if (map[i - 1][j] == 'S' && step[i - 1][j] != 0 && ans > step[i][j] + step[i - 1][j]) ret = step[i][j] + step[i - 1][j]; // 检查右边是否有相邻S if (map[i][j - 1] == 'S' && step[i][j - 1] != 0 && ans > step[i][j] + step[i][j - 1]) ret = step[i][j] + step[i][j - 1]; }
- Have Lunch Together
- Have Lunch Together
- 【hihocoder】 1092. Have Lunch Together
- hihocoder 1092 : Have Lunch Together
- #hihocoder #1092 : Have Lunch Together
- hihoCoder_#1092 Have Lunch Together(最短路)
- BFS-hihoCoder-第六十六周-Have Lunch Together
- hiho一下 第六十六周 Have Lunch Together
- 微软校招笔试题#1092 : Have Lunch Together详解以及源码分析
- lunch
- You have two down son! Brothers , together up !
- Together,
- 每日一句:My family will get together and have a big dinner.( 9.22 )
- business lunch
- Lunch Mode
- Lunch Time
- Lunch Time
- Lunch Rush
- Sublime Text的那些事
- HBase建表函数createTable的几点说明
- Gson解析(2)——Gson注解和GsonBuilder
- Python - 刷博客浏览数
- dp zoj3822 Domination
- Have Lunch Together
- HBase连接池 -- HTablePool被Deprecated以及可能原因是什么
- revit二次开发--获取element的三种方法
- QT5 学习之路21---文件对话框
- Android 自定义View (一)
- 【总结】Java基础总结⑷
- var_dump($user);die;
- Gson解析(3)——Map处理数据(上)
- HTablePool的实现分析