洛谷 P1825 [USACO11OPEN]玉米田迷宫Corn Maze

题目描述

去年秋天,奶牛们去参观了一个玉米迷宫,迷宫里有一些传送装置,可以将奶牛从一点到另一点进行瞬间转移。这些装置可以双向使用:一头奶牛可以从这个装置的起点立即到此装置的终点,同时也可以从终点出发,到达这个装置的起点。如果一头奶牛处在这个装置的起点或者终点,这头奶牛就必须使用这个装置。

玉米迷宫的外部完全被玉米田包围,除了唯一的一个出口。

这个迷宫可以表示为N×M的矩阵(2 ≤ N ≤ 300; 2 ≤ M ≤ 300),矩阵中的每个元素都由以下项目中的一项组成:

1、 玉米,这些格子是不可以通过的。

2、 草地,可以简单的通过。

3、 一个装置的结点,可以将一头奶牛传送到相对应的另一个结点。

4、出口

奶牛仅可以在相邻两个格子之间移动,要在这两个格子不是由玉米组成的前提下才可以移动。奶牛能在一格草地上可能存在的四个相邻的格子移动。从草地移动到相邻的一个格子需要花费一个单位的时间,从装置的一个结点到另一个结点需要花费0个单位时间。

被填充为玉米的格子用“#”表示,草地用“.”表示,每一对装置的结点由相同的大写字母组成“A-Z”,且没有两个不同装置的结点用同一个字母表示,出口用“=”表示。

Bessie在这个迷宫中迷路了,她知道她在矩阵中的位置,将Bessie所在的那一块草地用“@”表示。求出Bessie需要移动到出口处的最短时间。

例如以下矩阵,N=5,M=6:

###=##
#.W.##
#.####
#.@W##
######

唯一的一个装置的结点用大写字母W表示。

最优方案为:先向右走到装置的结点,花费一个单位时间,再到装置的另一个结点上,花费0个单位时间,然后再向右走一个,再向上走一个,到达出口处,总共花费了3个单位时间。

输入输出格式

输入格式:

 

第一行:两个用空格隔开的整数N和M;

第2-N+1行:第i+1行描述了迷宫中的第i行的情况(共有M个字符,每个字符中间没有空格。)

 

输出格式:

 

一个整数,表示Bessie到达终点所需的最短时间。

 

输入输出样例

输入样例#1: 
5 6
###=##
#.W.##
#.####
#.@W##
######
输出样例#1: 
3
分析
走迷宫加强版,每次多了瞬间传送的情况,注意判断细节即可(第一次写的时候竟然以为只有一个传送门W 23333).
其实我debug了一小时
wwx你要补偿我,肉偿
代码
#include<bits/stdc++.h>
using namespace std;

char mp[1000][1000];
int    book[1000][1000];
int n,m;
int beginx,beginy;

int move_beginx[30];
int move_beginy[30];
int move_endy[30];
int move_endx[30];

int changex[5]={0,0,1,0,-1};
int changey[5]={0,1,0,-1,0};

struct Point
{
    int x;
    int y;
    int step;
    Point(int _x,int _y,int _step):
        x(_x),y(_y),step(_step){}//构造函数 
};

queue<Point> q;
int ans;
int flag[30];

int main()
{
//    freopen("testdata.in","r",stdin);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>mp[i][j];
            if(mp[i][j]=='@')
            {
                beginx=i;
                beginy=j;
            }
            if(mp[i][j]>='A'&&mp[i][j]<='Z')
            {
                if(flag[mp[i][j]-'A']==0)
                {
                    flag[mp[i][j]-'A']=1;
                    move_beginx[mp[i][j]-'A']=i;
                    move_beginy[mp[i][j]-'A']=j;
                }
                else
                {
                    move_endx[mp[i][j]-'A']=i;
                    move_endy[mp[i][j]-'A']=j;
                }
            }//存储传送门 
        }
    }
    
    q.push(Point(beginx,beginy,0));
    book[beginx][beginy]=1;//记得起点标记 
    while(!q.empty())
    {
        Point now_node=q.front();
        q.pop();
        int now_x=now_node.x;
        int now_y=now_node.y;
//        cout<<now_x<<" "<<now_y<<" "<<mp[now_x][now_y]<<endl; 
        int now_step=now_node.step;
                
        for(int i=1;i<=4;i++)
        {
            int new_x=now_x+changex[i];
            int new_y=now_y+changey[i];

            if(new_x>n||new_x<1) continue;
            if(new_y>m||new_y<1) continue;
            if(mp[new_x][new_y]=='#') continue;
            if(book[new_x][new_y]==1) continue;

            book[new_x][new_y]=1;
            if(mp[new_x][new_y]=='=')
            {
                ans=now_step+1;
                goto u;
            }//搜到答案 

            if(mp[new_x][new_y]>='A'&&mp[new_x][new_y]<='Z')//提前打了标记不会存在传来传去的情况 
            {
                if((new_x==move_beginx[mp[new_x][new_y]-'A'])&&(new_y==move_beginy[mp[new_x][new_y]-'A']))
                {
                    if(move_endx[mp[new_x][new_y]-'A']==0) continue;
                    int jump_x=move_endx[mp[new_x][new_y]-'A'];
                    int jump_y=move_endy[mp[new_x][new_y]-'A'];
                    q.push(Point(jump_x,jump_y,now_step+1));
                }//传送门其中一端 
                else if((new_x==move_endx[mp[new_x][new_y]-'A'])&&(new_y==move_endy[mp[new_x][new_y]-'A']))
                {
                    if(move_beginx[mp[new_x][new_y]-'A']==0) continue;
                    int jump_x=move_beginx[mp[new_x][new_y]-'A'];
                    int jump_y=move_beginy[mp[new_x][new_y]-'A'];//不知道为什么直接赋值给new_x会挂,新开了个变量 
                    q.push(Point(jump_x,jump_y,now_step+1));
                }//另一端 
            }//是传送门 
            else
            {
                q.push(Point(new_x,new_y,now_step+1));
            }//不是传送门 
        }
    }
    u:cout<<ans<<endl;
    return 0;
}

 




posted @ 2018-11-03 21:41  前排吃瓜  阅读(352)  评论(0编辑  收藏  举报