1. 程式人生 > >洛谷 P1825 [USACO11OPEN]玉米田迷宮Corn Maze

洛谷 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.##
#.####
#
[email protected]
## ######

唯一的一個裝置的結點用大寫字母W表示。

最優方案為:先向右走到裝置的結點,花費一個單位時間,再到裝置的另一個結點上,花費0個單位時間,然後再向右走一個,再向上走一個,到達出口處,總共花費了3個單位時間。

輸入輸出格式

輸入格式:

 

第一行:兩個用空格隔開的整數N和M;

第2-N+1行:第i+1行描述了迷宮中的第i行的情況(共有M個字元,每個字元中間沒有空格。)

 

輸出格式:

 

一個整數,表示Bessie到達終點所需的最短時間。

 

輸入輸出樣例

輸入樣例#1: 
5 6
###=##
#.W.##
#.####
#[email protected]##
######
輸出樣例#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;
}