hdu-2364-Escape(bfs)

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).
这里写图片描述

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

2
9 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[N][N][4];
char map[N][N];
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值