计蒜客习题 蒜头君回家 BFS

 

第一次WA是因为仅仅想到模拟拿到钥匙后就从第一个钥匙的地方从零开始搜索,没有考虑到可能第一个钥匙的地方可能刚好和出口背道而驰,反而多走了几步路。那么就再开一维的空间,同时注意结构体里也要再加个flag标记,像一群蚂蚁一样地搜索。

注意下边这个样例:

30 30
..##..#.##.....#...#.#..##.##.
..#.P#P..#......PP.##....#P#..
.###.......##.#..##......#..#.
#....##P..#.......#.#...##.#.#
P.#..#..##.#P.....#..#.##....#
....#.P.P.##P.......#.#####...
.#.#.#.#.#.##.##.#.....#.P##..
.#..#..#.....#.#....P###......
..#..#...###P...#P#....#.P.P.#
.#.#.#####P...P#.####.......#.
##......#...#.#P..####.##..#.#
#..P...##...####..#.P.P#..#...
.....#....#.##.#...........#..
.###.S.#.#....#....P.P#..#..P#
.#.#...#.#...#.....#.##.##.#.P
##..##....#.#.P#.#..#..#.#.P##
....##...##.#....##.#....##.##
##.#...#.P..#.##..#.#.#####...
.##.....#.P.##.#...........#..
...##....####................#
P#.....###.....##..P.........#
.......P##..##P..#P...#..#...#
.#.##....P##..#.#..#.##....##P
##.######...#..#.##.P.##...#.#
.T..##.##.......##.#..........
.#...##.#..##P............#..#
..#.P..#.#.....#...#.#..####..
#P#.#....#.#...#...###.....#..
#..........#.P.......##....P##
..##....#P#.....#....##.#....#

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <queue>
#include <stack>
using namespace std;
#define el else

struct P{
    int x,y;
    int cnt;        //记录步数
    int fj;         //标记当前有没有拿到钥匙
    P(int xx,int yy,int cc,int ff):x(xx),y(yy),cnt(cc),fj(ff){}
};

int n,m;
int dir[4][2] = {0,1,1,0,0,-1,-1,0};
char maze[2005][2005];
bool vis[2005][2005][2];       //这里多开一维数组,类似于一个平行空间,可以通过记录一个状态后重复搜索已经走过的路

void bfs(int xx,int yy){
    queue<P> q;
    P tej(xx,yy,0,0);
    q.push(tej);
    vis[xx][yy][0] = 1;

    while(!q.empty()){
        tej = q.front();        //记录栈顶第一个点的状态
        q.pop();
        if(maze[tej.x][tej.y] == 'P'){
                tej.fj = 1;     //拿到钥匙后标记,进入一个新的次元
        }
        if(maze[tej.x][tej.y] == 'T' && tej.fj == 1){
            printf("%d\n",tej.cnt); //如果搜索到且有钥匙直接输出
            return;
        }
        for(int i=0; i<4; ++i){
            int tx = tej.x + dir[i][0];
            int ty = tej.y + dir[i][1];
                            if(tx <0 || ty<0 || tx>=n || ty>=m) continue;//骚操作,学习了
            if(maze[tx][ty]!='#' && !vis[tx][ty][tej.fj]){
                q.push(P(tx,ty,tej.cnt+1,tej.fj));
                vis[tx][ty][tej.fj] = 1;    //给这个次元的点上色
            }
        }
    }
    return;
}

int main()
{
    int fl = 0;
    int x,y;
    scanf("%d%d",&n,&m);
    for(int i=0; i<n; ++i)
    {
        scanf("%s",maze[i]);
        int len = strlen(maze[i]);
        if(fl == 0)                     //
            for(int j=0; j<len; ++j)
            {
                if(maze[i][j]=='S')
                {
                    x=i;
                    y=j;
                    fl=1;
                    break;
                }
            }                           //这一坨都是为了找起点
    }
    memset(vis,0,sizeof(vis));
    bfs(x,y);
    return 0;
}











 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值