hud5040 InstrusiveBFS+优先队列

这道题的题意是,你从M点到T点,然后中间有开始可能W,E,N,S四个方向的摄像头,摄像头的照射空间是它本身和它前面的那个格子,当你下一秒要去的格子正在被摄像头照射时,你要不然就是等一秒(这里是重点,就是按理来说摄像头下一秒会离开这个点,然后你恰好可以去,然而实际这道题却并不是这样,只能等),要不然就是藏在箱子里用3秒过去,当正好是摄像头时,则只能用箱子用三秒通过,那么最短的时间是多少呢,如若不能则输出-1(可能有墙,你是过不去的)
这道题其实就是一道BFS+优先队列,有四种情况,1.有摄像头,2.被摄像头照射,3.空地且不被摄像头照射,4.墙,策略:遇到情况1,要走,时间加3,第二种情况,要停等待一秒,时间加1位置不变,情况3,走,时间加1 ,情况4可以直接跳过不操作,对于摄像头转向问题,用时间%4就可以计算出当前摄像头方向了;

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
using namespace std;
int dx[4]= {0,-1,0,1};
int dy[4]= {-1,0,1,0};
const int maxn=510;
char str[maxn][maxn];
bool vis[maxn][maxn][5];
int n;
int p[maxn];
struct node//优先队列的自定义排序模板
{
    int x,y,t;
    friend bool operator<(node a,node b)
    {
        return a.t>b.t;
    }
};
int check(int x,int y,int t)
{
    if(x<0||x>=n||y<0||y>=n||str[x][y]=='#')
        return 0;
    if(p[str[x][y]]!=-1)
        return 1;
    int nx,ny,nowt;
    for(int i=0; i<4; i++)
    {
        nx=dx[i]+x;
        ny=dy[i]+y;
        if(nx<0||nx>=n||ny<0||ny>=n||str[nx][ny]=='#')
            continue;
        int temp=p[str[nx][ny]];
        if(temp>=0&&(temp+t)%4==i)
            return 1;
        /*temp+=t; if(temp>4) temp%=4; if(i==0&&temp==1) return false; if(i==1&&temp==4) return false; if(i==2&&temp==3) return false; if(i==3&&temp==2) return false; */
    //这个地方充分的解释了你下一步要走的格子正好被摄像头照上的情景,就是让两者正好对上

    }
    return 2;
}

int bfs(int fx,int fy)
{
    priority_queue<node>q;
    memset(vis,0,sizeof(vis));
    node k1;
    k1.x=fx;
    k1.y=fy;
    k1.t=0;
    q.push(k1);
    while(!q.empty())
    {
        node now=q.top();
        q.pop();
        if(str[now.x][now.y]=='T')
            return now.t;
        int next_x,next_y,next_t;
        next_t=now.t+1;//这里是等一秒钟的情况
        if(!vis[now.x][now.y][next_t%4])
        {
            vis[now.x][now.y][next_t%4]=true;
            node k2;
            k2.x=now.x;
            k2.y=now.y;
            k2.t=next_t;
            q.push(k2);
        }
        int nowv=check(now.x,now.y,now.t);
        for(int i=0; i<4; i++)
        {
            next_x=dx[i]+now.x;
            next_y=dy[i]+now.y;
            int sta=check(next_x,next_y,now.t);
            if(sta==0)
                continue;
            else  if(sta==1||nowv==1)//当前状态被照射或者下一位置被照射 
                next_t=now.t+3;
            else if(sta==2)//畅通无阻
            {
                next_t=now.t+1 ;
            }
            if(!vis[next_x][next_y][next_t%4])
            {
                vis[next_x][next_y][next_t%4]=true;
                node k3;
                k3.x=next_x;
                k3.y=next_y;
                k3.t=next_t;
                q.push(k3);
            }
        }
    }
    return -1;
}
int main()
{
    int T=1;
    int t,mi,mj;
    cin>>t;
    while(t--)
    {
        int ans=0;
        cin>>n;
         memset(p,-1,sizeof(p));
        p['E']=0,p['S']=1,p['W']=2,p['N']=3;
//这个不是随随便便定义的,要恰好和上面定义的数组能对应上,而且,坐标系y轴向下为正,这个点我错过好几次
        for(int i=0; i<n; i++)
        {
            cin>>str[i];
            for(int j=0; j<n; j++)
            {
                if(str[i][j]=='M')
                {
                    mi=i;
                    mj=j;
                }
            }
        }
        ans=bfs(mi,mj);
        printf("Case #%d: %d\n",T++,ans);
    }
    return 0;

}

你可能感兴趣的:(搜索,图论)