[BZOJ3299]&&[USACO2011 Open]Corn Maze 玉米迷宫

描述 Description

今年秋天,约翰带着奶牛们去玩玉米迷宫。迷宫可分成 NxM 个格子,有些格子种了玉米,种宥玉米的格子无法通行。迷宫的四条边界上都是种了玉米的格子,其屮只有一个格子没种,那就是出口。在这个迷宫里,有一些神奇的传送点 6 每个传送点由一对点组成,一旦走入传送点的某个结点,机器就会强制把你送到传送点的另一头去。所有的传送点都是双向 的,如果你定到了另一头,机器也会把你送回来。

奶牛在一个单位的时间内只能向相邻的四个方向移动一格,不过传送机传送是瞬间完成的。

现在 W 西在迷宫里迷路了,她只知道目前的位罝在哪里,请你帮助她用最短的时间走出 迷宫吧。

描述了迷宫第 i 行的信息。其中 “#” 代 表不能通行的玉米地,“.” 代表可以通行的草地,“@” 代表贝西的起始位罝,“=” 代表迷宫出口,大写字母 “A” 到“Z”总是成对出现的,代表一对传送点.

输出格式 OutputFormat

第一行:一个整数,表示贝西走出迷宫的最短时间,保证逃离迷宮的路线一定存在.

样例输入 SampleInput

37 70
######################################################################
#….#TCP#…………………………………………………..#
#….#####…..#……#……………………………………….#
#………….#.#….#.#………………………………………#
#…………..######W#……………………………………….#
#………….#……..#..##############################………….#
#…………#..V….V..#..#……………………….#..#…#…..#
#………….#……..#….#……………………….#..#.#.#….#
#………….#..X##X..#..#……………W……………#..#…#…#
#…………#…N##N…#..#………………………..#………..#
#……..MOO..#..@…..#….#.#.#.#……………….#.#…………#
#…………..########…..#.#.#.##############.#.#..#.#…………#
#………………………#.#.#.#………….#.#.#.#.#…………#
#…….#########………..#.#.#.#……………..#.#.#…………#
#……#………#……….#.#.#.#……………..#.#.#…………#
#..#.#.#G#R#A#S#S#.#.#……#.#.#.#……………..#.#I#…………#
#..###################……#T#C#P#……………..#I#G#…………#
#……………………….#.#.#……………….#.#………….#
#…………………………………………………………..#
#…………………………………………………………..#
#……########……..########…….#………..#………..#……#
#…..#……………#R……A#…….#………#.#………#…….#
#…..#……………#……..#……..#…….#…#…….#……..#
#…..#……………#……..#………#…..#…..#…..#………#
#…..#……………#……..#……….#…#…….#…#……….#
#…..#……………#..M…..#………..#.#………#.#………..#
#……########……..########………….#………..#…………#
#…………………………………………………………..#
#…………………………………………………………..#
#…………………………………………………………..#
####################################################################.#
#…………………………………………………………..#
##.###################################################################
#..#F#ZD#.#Y#.#JL#.#…#QJ#.#.#.#.#EK#….#.L#………….#BQ#……#
#.##Z####.#U#.####.#.#.####.#.#.#.####.#..####………….####.####.#
#….#DE#.###.#UH#…#.#HK#.#.#.#.#F…#……………………#BY#.#
####################################################################=#

样例输出 SampleOutput

232


BZOJ 3299


代码 Code

bfs。遇到传送门的时候修改一下对应的坐标即可。

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
int i,j,t,n,m,l,r,k,z,y,x;
const int dx[5]={0,0,0,1,-1};
const int dy[5]={0,1,-1,0,0};
map < char,pair<int,int> > m1,m2;
char a[305][305],ch;
bool used[305][305];
struct point
{
    int x,y,z;
};
deque <point> f;
pair <int,int> endp;
inline void change(int &x,int &y)
{
    map < char,pair<int,int> > ::iterator i,j;
    if (!m1.count(a[x][y])) return ;
    i=m1.find(a[x][y]);
    j=m2.find(a[x][y]);
    if (i->second==make_pair(x,y))
    {
        x=j->second.first;
        y=j->second.second;
        return ;
    }
    if (j->second==make_pair(x,y))
    {
        x=i->second.first;
        y=i->second.second;
        return ;
    }
}
inline int bfs()
{
    int i,j,t,tx,ty;
    while (!f.empty())
    {
        x=f.front().x;y=f.front().y;z=f.front().z;f.pop_front();
        if (endp==make_pair(x,y)) return z;
        for (i=1;i<=4;i++)
        {
            tx=x+dx[i];ty=y+dy[i];
            if (a[tx][ty]!='=' && a[tx][ty]!='.' && a[tx][ty]!='#' && a[tx][ty]!='@') change(tx,ty);
            if (!used[tx][ty])
            {
                used[tx][ty]=true;
                if (!f.empty() && z+1<f.front().z)
                {
                    f.push_front((point){tx,ty,z+1});
                }
                else f.push_back((point){tx,ty,z+1});
            }
        }
    }
}
int main()
{
    memset(used,false,sizeof(used));
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++)
    {
        scanf("%s",a[i]+1);
        for (j=1;j<=m;j++)
        {
            if (a[i][j]=='@')
            {
                f.push_back((point){i,j,0});
                continue;
            }
            if (a[i][j]=='=')
            {
                endp=make_pair(i,j);
                continue;
            }
            if (a[i][j]=='#')
            {
                used[i][j]=true;
                continue;
            }
            if (a[i][j]!='.')
            {
                if (m1.count(a[i][j])) m2.insert(make_pair(a[i][j],make_pair(i,j)));
                else m1.insert(make_pair(a[i][j],make_pair(i,j)));
            }
        }
    }
    printf("%d\n",bfs());
    return 0;
}