1. 程式人生 > >2018 ACM-ICPC北京網路賽 A.Saving Tang Monk II(bfs)

2018 ACM-ICPC北京網路賽 A.Saving Tang Monk II(bfs)

好久沒bfs了,沒想到用三維陣列去標記狀態來進行bfs。。。但仔細一想想,這麼解很有道理。。。

因為這個圖每個格子可以走多遍,我們考慮,對於一個格子,如果帶著相同的氧氣瓶走兩次,那結果是相同的。所以我們從這個約束進行搜尋,開一個三位數字,vis[i][j][k]代表帶著k個氧氣瓶走到第[i][j]個格子。然後就是進行討論。

我們要求到達終點的時間最短,所以可以用優先佇列進行bfs,首先到達終點的肯定是時間最短的。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
int vis[150][150][6];
int dis[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
char ma[150][150];
int n,m;
struct Node
{
    int x;
    int y;
    int t;
    int b;
    Node(int xx=0,int yy=0,int tt=0,int bb=0):x(xx),y(yy),t(tt),b(bb) {}
    bool operator <(const Node &a)const
    {
        return t>a.t;
    }
};//優先佇列按時間遞增排序。
priority_queue<Node>Q;
int xt,yt;
int bfs()
{
    Node top;
    int tx,ty;
    while(!Q.empty())
    {
        //cout<<"---"<<endl;

        top=Q.top();
        //cout<<top.x<<" "<<top.y<<endl;
        Q.pop();

        for(int i=0; i<4; i++)
        {
            tx=top.x+dis[i][0];
            ty=top.y+dis[i][1];
            if(tx>=1&&tx<=n&&ty>=1&&ty<=m)
            {//cout<<"+++"<<tx<<" "<<ty<<" "<<top.b<<" "<<vis[tx][ty][top.b-1]<<endl;
                if(ma[tx][ty]=='#')
                {
                    if(top.b<1)continue;//沒有氧氣瓶不能進入毒氣室
                }
               if(ma[tx][ty]=='#'&&top.b>=1&&!vis[tx][ty][top.b-1])//可以進入
                {
                    vis[tx][ty][top.b-1]=1;//標記狀態 不用重複搜尋
                    Q.push(Node(tx,ty,top.t+2,top.b-1));//時間增加2,用掉一個氧氣瓶
                }
                if(ma[tx][ty]=='.'&&!vis[tx][ty][top.b])
                {
                    vis[tx][ty][top.b]=1;
                    Q.push(Node(tx,ty,top.t+1,top.b));
                }
                if(ma[tx][ty]=='P'&&top.t>=0&&!vis[tx][ty][top.b])
                {
                     vis[tx][ty][top.b]=1;
                    Q.push(Node(tx,ty,top.t,top.b));//因為是P,所以不需要時間
                }
                if(ma[tx][ty]=='B'&&top.b<5&&!vis[tx][ty][top.b+1])//最多隻能帶5個,需要判斷
                {
                     vis[tx][ty][top.b+1]=1;
                    Q.push(Node(tx,ty,top.t+1,top.b+1));
                }
                if(ma[tx][ty]=='S'&&!vis[tx][ty][top.b])//注意S可以重複走
                {
                     vis[tx][ty][top.b]=1;
                    Q.push(Node(tx,ty,top.t+1,top.b));
                }
                if(ma[tx][ty]=='T')
                {
                    return top.t+1;
                }

            }
        }
    }
    return -1;
}
int main()
{

    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0)break;
        memset(vis,0,sizeof(vis));
        while(!Q.empty())Q.pop();
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                cin>>ma[i][j];
                if(ma[i][j]=='S')
                {
                    Q.push(Node(i,j,0,0));
                    vis[i][j][0]=1;
                }
                if(ma[i][j]=='T')
                {
                    xt=i;
                    yt=j;
                }
            }
        }
        int ans=bfs();
        printf("%d\n",ans);
    }
}