hiho一下 第六十六周
2015-10-10 15:24
375 查看
题意分析
给定一幅字符表示的地图,其中包含有 1 个起点’H’,若干个座位’S’,墙壁’#’和行人’P’。
其中墙壁’#’和行人’P’是不可通过的区域。
假设在地图中,只能沿着上下左右移动,且每移动一个单元格为 1 步。
询问从’H’点出发,是否能够到达两个相邻的’S’,且需要移动的步数最少是多少。
算法分析
从题目当中,我们就可以知道本题需要做什么:
那么我们就按照这三个步骤来解决这道题目。
首先是数据的读入,由于输入数据中已经明确的告诉了我们地图为 N 行 M 列,所以我们只需要一行一行读入字符串,并使用char map
[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);
// 查找起点H
for (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
[M],step[i][j]表示从起点到(i,j)的最少步数。
初始化为step[i][j] = INT_MAX,默认为任何点都无法到达。
开始遍历时,将step[ startX ][ startY ]设定为0,并以(startX, startY)开始BFS整个地图。
在遍历整个地图的过程中我们需要注意:
最后当没有新的节点可以到达时,退出BFS,得到整个地图的step
[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
给定一幅字符表示的地图,其中包含有 1 个起点’H’,若干个座位’S’,墙壁’#’和行人’P’。
其中墙壁’#’和行人’P’是不可通过的区域。
假设在地图中,只能沿着上下左右移动,且每移动一个单元格为 1 步。
询问从’H’点出发,是否能够到达两个相邻的’S’,且需要移动的步数最少是多少。
算法分析
从题目当中,我们就可以知道本题需要做什么:
读取字符地图,并找到起点的位置。 从起点开始,遍历该地图,记录到达每一个'S'的距离。 判断是否有两个相邻的'S'都可达,若存在多个解,则需要找到最小的值。
那么我们就按照这三个步骤来解决这道题目。
首先是数据的读入,由于输入数据中已经明确的告诉了我们地图为 N 行 M 列,所以我们只需要一行一行读入字符串,并使用char map
[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);
// 查找起点H
for (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
[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
[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
#include <cstdio> #include <queue> #include <algorithm> using namespace std; int dx[4] = {0, 0, 1, -1}; int dy[4] = {1, -1, 0, 0}; char Map[110][110]; int N, M, step[110][110], rec[110][110]; void BFS(int X, int Y) { queue <pair <int, int> > q; q.push(make_pair(X, Y)); while(!q.empty()) { X = q.front().first; Y = q.front().second; q.pop(); for (int i = 0; i < 4; i++) { int x = X + dx[i]; int y = Y + dy[i]; if (x >= 0 && x < N && y >= 0 && y < M && (Map[x][y] == '.' || Map[x][y] == 'S') && !rec[x][y]) { rec[x][y] = 1; step[x][y] = step[X][Y] + 1; if (Map[x][y] == '.') q.push(make_pair(x, y)); } } } } int main() { scanf("%d%d", &N, &M); for (int i = 0; i < N; i++) scanf("%s", Map[i]); for (int i = 0; i < N; i++) for (int j = 0; j < M; j++) if (Map[i][j] == 'H') BFS(i, j); int ans = 0x3f3f3f3f; for (int i = 0; i < N; i++) for (int j = 0; j < M; j++) if (Map[i][j] == 'S' && step[i][j]) for (int k = 0; k < 4; k++) { int x = i + dx[k]; int y = j + dy[k]; if (x >= 0 && x < N && y >= 0 && y < M && Map[x][y] == 'S' && step[x][y]) ans = min(ans, step[i][j] + step[x][y]); } if (ans != 0x3f3f3f3f) printf("%d\n", ans); else puts("Hi and Ho will not have lunch."); return 0; }
相关文章推荐
- Hash Table哈希表和Hash List哈希链表的知识汇总
- 文件描述符和套接字
- 我的进阶曲线之七
- 我的进阶曲线之八
- lamp安装总结
- Last Defence - UVA7045
- 自学编程的那些事
- 在ViewPager中的Fragment添加控件及TextureView
- 我的进阶曲线之六
- 【未完】mail邮件报警系统搭建
- extjs中store的reload事件异步问题解决
- Redis详解——常用命令总结(完善中)
- 转载:个人电子技术经验积累
- centos7 nfs服务器配置
- @font-face
- openwrt增加自己应用步骤
- request_irq() | 注册中断服务参考
- android 学习 IPC机制
- 近期的总结
- 【学习】RecyclerView