hdu-2364-Escape(bfs)
2016-01-17 16:43
357 查看
Problem Description
You find yourself trapped in a large rectangular room, made up of large square tiles; some are accessible, others are blocked by obstacles or walls. With a single step, you can move from one tile to another tile if it is horizontally or vertically adjacent (i.e. you cannot move diagonally).To shake off any people following you, you do not want to move in a straight line. In fact, you want to take a turn at every opportunity, never moving in any single direction longer than strictly necessary. This means that if, for example, you enter a tile from the south, you will turn either left or right, leaving to the west or the east. Only if both directions are blocked, will you move on straight ahead. You never turn around and go back!
Given a map of the room and your starting location, figure out how long it will take you to escape (that is: reach the edge of the room).
![](http://acm.hdu.edu.cn/data/images/C145-1005-1.jpg)
Input
On the first line an integer t (1 <= t <= 100): the number of test cases. Then for each test case:a line with two integers separated by a space, h and w (1 <= h, w <= 80), the height and width of the room;
then h lines, each containing w characters, describing the room. Each character is one of . (period; an accessible space), # (a blocked space) or @ (your starting location).
There will be exactly one @ character in each room description.
Output
For each test case:A line with an integer: the minimal number of steps necessary to reach the edge of the room, or -1 if no escape is possible.
Sample Input
29 13
#############
#@……….#
#####.#.#.#.#
#………..#
#.#.#.#.#.#.#
#.#…….#.#
#.#.#.#.#.#.#
#………..#
#####.#######
4 6
#.####
#.#.##
#…@#
######
Sample Output
31-1
题意:求起始点到任意一条边的最短距离。规则是:可以拐弯的话就不能直走,否则直走
思路:BFS,不过vis的标记数组要变成三维的,记录从四个方向进来的可能
#include <iostream> #include <iomanip> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <cmath> #include <queue> #include <algorithm> #define N 88 const int mm = 1000000007; using namespace std; const int dir[4][2]={1, 0, 0, 1, -1, 0, 0, -1}; struct node { int x, y, step, dir; }s; int n, m; int vis [4]; char map ; int bfs() { queue<node> q; node t1, t2; bool flag; int i, x, y, d; q.push(s); memset(vis, 0, sizeof(vis)); vis[s.x][s.y][0] = vis[s.x][s.y][1] = vis[s.x][s.y][2] = vis[s.x][s.y][3] = true; while(!q.empty()) { t1 = q.front(); q.pop(); flag = false; if (t1.x == 0 || t1.x == n-1 || t1.y == 0 || t1.y == m-1) return t1.step; for (i = 0; i < n; i++) { if (t1.dir < 0 || (t1.dir&1) != (i&1)) { t2.dir = i; t2.step = t1.step + 1; t2.x = t1.x + dir[i][0]; t2.y = t1.y + dir[i][1]; if (t2.x < 0 || t2.y < 0 || t2.x >= n || t2.y >= m || map[t2.x][t2.y] == '#') continue; flag = true; if (vis[t2.x][t2.y][i]) continue; vis[t2.x][t2.y][i] = 1; q.push(t2); } } if (!flag) { t2.dir = t1.dir; t2.step = t1.step + 1; t2.x = t1.x + dir[t1.dir][0]; t2.y = t1.y + dir[t1.dir][1]; if (t2.x < 0 || t2.y < 0 || t2.x >= n || t2.y >= m || map[t2.x][t2.y] == '#') continue; if (map[t2.x][t2.y] != '#' && !vis[t2.x][t2.y][t1.dir]) { vis[t2.x][t2.y][t1.dir] = 1; q.push(t2); } } } return -1; } int main() { #ifndef ONLINE_JUDGE freopen("1.txt", "r", stdin); #endif ios::sync_with_stdio(false); cin.tie(0); int i, j, T; cin >> T; while(T--) { cin >> n >> m; for (i = 0; i < n; i++) { cin >> map[i]; for (j = 0; j < m; j++) { if (map[i][j] == '@') { s.x = i; s.y = j; } } } s.step = 0; s.dir = -1; cout << bfs() << endl; } return 0; }
相关文章推荐
- HTTP请求报文和HTTP响应报文
- IOS开发OC 如何将导航栏左侧系统自动生成的返回按钮的文字去掉,只保留小于号"<"图案
- Android界面设计的4种方式之三——使用XML和JAVA代码混合控制UI界面
- malloc和memcpy简单介绍
- pythonchallenge(25-28)
- akka 学习笔记
- 4、React对组件的DOM事件监听
- checkbox选取,全选
- reset命令不见了!!调试u-boot遇到的怪问题
- pythonchallenge(21-24)
- 使用ssh远程登录linux
- 配置python环境变量(转)
- 随机接入过程
- UI组件之AdapterView及其子类(六)ExpandableListView组件和ExpandableListActivity的使用
- 使用python,scrapy写(定制)爬虫的经验,资料,杂。
- token生成过程
- shell 编程入门
- Xcode 写代码没有补全提示解决:删缓存及显示隐藏文件命令
- Android View 滚轮控件LoopView+自定义Dialog [时间地域选择器] Picker
- oracle开机启动脚本