您的位置:首页 > 其它

hdu 5040 Instrusive(bfs+优先队列)(模拟)

2015-09-19 10:57 405 查看
题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5040

解题思路:

题目大意:

给你一个图,里面有起点,终点,和监视器的位置,每个监视器有东南西北的初始朝向,每个监视器的监视范围是两格(自身所在

区域算一个),每过1秒钟,所有监视器的所朝方向都会顺时针旋转90度,从被监视位置到其他的任何位置都需要消耗3秒钟,从其

他位置进入被监视位置需要3秒钟,其他的情况消耗1秒钟,当处于被监视位置时也可以停留若干秒,等处于非监视状态再继续,问

从起点到终点的最短时间。

算法思想:

bfs+优先队列,状态保存需要坐标(x,y)还有时间tmpt%4这三个元素就行了。

AC代码:

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 505;
const int dx[] = {0,-1,0,1},dy[] = {-1,0,1,0};
//E==0,S==1,W==2,N==3
int n;
int dir[110];
bool vis[maxn][maxn][5];
char a[maxn][maxn];

struct node{
    int x,y,t;
    bool operator < (const node &s) const{
        return t > s.t;
    }
};

int Check(int x,int y,int t){
    //return 1代表该位置当前被灯照到,2代表当前位置没有灯照射,也可以走,0代表不可达
    if(x<1 || x>n || y<1 || y>n || a[x][y]=='#')
        return 0;
    if(dir[a[x][y]] != -1)
        return 1;
    for(int i = 0; i < 4; i++){
        //要知道当前点有没有被照到,需要查看当前点四个方向上有没有灯朝向这个点
        int xx = x+dx[i],yy = y+dy[i];
        if(xx<1 || xx>n || yy<1 || yy>n)
            continue;
        int tmp = dir[a[xx][yy]];//tmp>=0代表当前点有灯
        if(tmp>=0 && (tmp+t)%4==i)
            return 1;
        //(tmp+t)代表当前时间,%4代表此时灯的转向,稍微设计了一下方向函数dir,使得(tmp+t)==i的时候,说明该点被照到
    }
    return 2;
}

int bfs(int sx,int sy){
    memset(vis,0,sizeof(vis));
    priority_queue<node> que;
    que.push((node){sx,sy,0});
    while(!que.empty()){
        node cur = que.top();
        que.pop();
        if(a[cur.x][cur.y] == 'T')
            return cur.t;
        int tmpt;
        //不移动的情况
        tmpt = cur.t+1;
        if(!vis[cur.x][cur.y][tmpt%4]){
            vis[cur.x][cur.y][tmpt%4] = 1;
            que.push((node){cur.x,cur.y,tmpt});
        }
        int flag = Check(cur.x,cur.y,cur.t);//flag=1说明当前点被照亮
        for(int i = 0; i < 4; i++){
            int xx = cur.x+dx[i],yy = cur.y+dy[i];
            int check = Check(xx,yy,cur.t);
            if(check == 0)
                continue;
            if(check==1 || flag==1)
                tmpt = cur.t+3;//要移动的点或者当前点被照亮
            else if(check == 2)
                tmpt = cur.t+1;
            if(!vis[xx][yy][tmpt%4]){
                vis[xx][yy][tmpt%4]=1;
                que.push((node){xx,yy,tmpt});
            }
        }
    }
    return -1;
}

int main(){
    memset(dir,-1,sizeof(dir));
    dir['E'] = 0,dir['S'] = 1,dir['W'] = 2,dir['N'] = 3;
    int T,t = 1;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i = 1; i <= n; i++)
            scanf("%s",a[i]+1);
        int sx,sy;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                if(a[i][j] == 'M'){
                    sx = i,sy = j;
                    break;
                }
        int ans = bfs(sx,sy);
        printf("Case #%d: %d\n",t++,ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: