HDU 5040 Instrusive(搜索,bfs,2014北京网络赛1009)

题目:Instrusive

题意:给定一个地图,要从'M'点到'T'点,每次可以往四个方向移动,平时每次移动1格花费1秒。但是由于地图上有一些监控,如果当前所在格被监控看到,就必须躲在纸箱里,躲在纸箱里移动一格的耗时是3秒。而监控的可视范围是它本身所在的一格,以及它朝向的相邻一格。监控每秒会顺时针旋转90度。地图上还有一些‘#'标记表示不可以进入的。

最后求M'到'T'的最短时间,不能到达输出-1。

因为每个监控都是1秒旋转90度,换句话说,所有监控的朝向都是可以通过时间来判断的,而当前时间T监控的朝向,跟它在T%4的时候是一样的。所以可以将地图按照模4分成4层,在预处理的时候就标记好对应模4的时刻哪些点是被监控到的。

再来是移动,对于当前结点,由于进出纸箱是不耗时的。所以如果是在本地停留1秒的话,不管有没有被监控,都是转移到这个点的下一秒。

如果打算移动了,就看看当前格和下一格是否在当前时刻会被监控,如果两个都没有被监控,移动花费是1,否则是3。

确定了这些之后就是写个bfs了,标记好哪些状态已经被访问过就行了。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N = 510;
char map[N][N];
bool ban[N][N][4], vis[N][N][4];
struct Node{
    int x, y, u;
    Node(){}
    Node(int x, int y, int u):x(x),y(y),u(u){}
    bool operator < (const Node &A)const{
        return u > A.u;
    }
};
int xl[4]={-1,0,1,0};
int yl[4]={0,1,0,-1};
int getd(char ch){
    if(ch=='N') return 0;
    if(ch=='E') return 1;
    if(ch=='S') return 2;
    if(ch=='W') return 3;
    return -1;
}
int T, n, sx, sy;
int solve(){
    memset(vis, 0, sizeof(vis));
    priority_queue<Node> Q;
    Q.push(Node(sx, sy, 0));
    while(!Q.empty()){
        Node nd=Q.top(); Q.pop();
        if(vis[nd.x][nd.y][nd.u%4]) continue;
        if(map[nd.x][nd.y]=='T')    return nd.u;
        vis[nd.x][nd.y][nd.u%4]=1;
        Q.push(Node(nd.x, nd.y, nd.u+1));
        for(int i=0; i<4; i++){
            int a = nd.x + xl[i];
            int b = nd.y + yl[i];
            if(a<0 || a>=n || b<0 || b>=n)  continue;
            if(map[a][b]=='#')  continue;
            int u = nd.u;
            if(ban[a][b][nd.u%4] || ban[nd.x][nd.y][nd.u%4]){
                u += 3;
            }
            else{
                u++;
            }
            if(!vis[a][b][u%4]) Q.push(Node(a,b,u));
        }
    }
    return -1;
}
int main(){
    scanf("%d",&T);
    for(int t=1; t<=T; t++){
        scanf("%d", &n);
        memset(ban, 0, sizeof(ban));
        for(int i=0; i<n; i++){
            scanf("%s", map[i]);
            for(int j=0; j<n; j++){
                if(map[i][j]=='M'){
                    sx=i; sy=j;
                }
                else{
                    int d = getd(map[i][j]);
                    if(~d){
                        for(int k=0; k<4; k++){
                            ban[i][j][k] = 1;
                            int x = i + xl[(d+k)%4];
                            int y = j + yl[(d+k)%4];
                            if(x<0 || x>=n || y<0 || y>=n)  continue;
                            ban[x][y][k] = 1;
                        }
                    }
                }
            }
        }
        printf("Case #%d: %d\n", t, solve());
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值