bench与奔驰

Problem 38: bench与奔驰


Time Limit:1 Ms|  Memory Limit:128 MB
Difficulty:2

Description

公园里有个人在练开奔驰 - -!,但是总是撞在bench上 (众人曰:狼来了,快跑啊!)
公园里的bench与奔驰都是无敌的,不会被撞坏。
由于开奔驰的人比较"有特点",总是向上下左右四个方向开,而且只会在撞到椅子之后改变方向(起步时除外) - -!
现在他给你一张地图,上面标明 他的位置 、 公园里的bench的位置 和 他想到达的位置,可能会有冲出地图的可能
请你告诉他最少撞多少下才能到达目的地,并答应事成之后会给你一辆奔驰..............................................的照片

Input

第一行,两个数,分别表示地图的行和列,都不大于50
以下是地图,"."表示地面,"S"表示起点,"E"表示终点,"B"表示bench(什么意思呢?)
保证只有一个终点和一个起点,并不会出现其他字符

Output

第一行,表示他能不能到达目的地。如果能,就输出"Yes"。否则,输出"No"
如果能到达目的地,就在第二行输出最少的撞击次数

Sample Input

测试数据1:
5 5
BBBBB
B...B
BSE.B
B...B
BBBBB

测试数据2:
3 3
S..
...
..E

Sample Output

测试数据1:
Yes
0

测试数据2:
No

Hint

测试数据1:点火后直接向右走
测试数据2:四个方向都会冲出地图

思路:一道深搜题, 搜索的时候要直着走遇到障碍才能转向, 标记的时候可以直接标

记转弯的地方, 避免重复搜索, 因为每次搜索开始时原始方向必定撞墙, 所以来的方

向和原始方向不用再搜, 每次遇到‘B’时展开下次搜索, 因为要找到hit最小是的路径所

以要遍历完才知道谁最小。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#define MAX 55

using namespace std;

typedef struct Pos
{
    int x;
    int y;
    int hit;                                //撞击次数
}pos;

pos sp, ep;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, n, m, minn;
char map[MAX][MAX];

void dfs(pos prepos, int predir)              //搜索起点, 原始方向
{
	
    for(int i = 0; i < 4; i++)
    {
		if((i == predir) || (i == 0 && predir == 1) || (predir == 0 && i == 1) || (predir == 2 && i == 3) || (predir == 3 && i == 2))
		{  //此处判断方向是否合适(来的方向不搜(搜过), 原始方向不搜(因为已经堵了),为了节省时间)
			continue;
		}
        pos t;
        t.x = prepos.x + dir[i][0];
        t.y = prepos.y + dir[i][1];
        while(t.x >= 0 && t.x < n && t.y >= 0 && t.y < m && map[t.x][t.y] == '.')     //走到头
        {    
            t.x = t.x + dir[i][0];
            t.y = t.y + dir[i][1];
        }
        if(map[t.x][t.y] == 'E')                  //到达终点, 判断hit是否为最小
        {
            if(prepos.hit < minn)
            {
                minn = prepos.hit;                //更新最小hit值
            }
            continue;
        }
        if(map[t.x][t.y] == 'B')                   //如果撞墙, 展开下一次深搜
        {
            t.x -= dir[i][0];
            t.y -= dir[i][1];
			if(map[t.x][t.y] == 'X')              //有可能是已经搜过的点(必须加上,否则死循环)
			{
				continue;
			}
            t.hit = prepos.hit + 1;
            map[t.x][t.y] = 'X';
            dfs(t, i);
            map[t.x][t.y] = '.';                   //搜完还原标记
        }
    }
}

int main()
{
    int i, j;
    cin>>n>>m;
    for(i = 0; i < n; i++)
    {
        for(j = 0; j < m; j++)
        {
            cin>>map[i][j];
            if(map[i][j] == 'S')
            {
                sp.x = i;
                sp.y = j;
                sp.hit = 0;
                map[i][j] = 'X';      //标记为已搜
            }
            else if(map[i][j] == 'E')
            {
                ep.x = i;
                ep.y = j;
            }
        }
    }
    minn = 0xfffff;                  //初始化为一个大于50*50的数
    dfs(sp, -1);                     //注意此处的方向, 以为搜的时候不会搜来的方向和原始方向, 所以要初始化成一个无效的方向, 第一次才会搜四个方向
    if(minn != 0xfffff)              //没变化?说明没搜到
    {
        cout<<"Yes"<<endl<<minn<<endl;
    }
    else
    {
        cout<<"No"<<endl;
    }
    return 0;
}


你可能感兴趣的:(搜索,遍历,DFS)