Instrusive (优先队列bfs)

The legendary mercenary Solid Matt gets a classic mission: infiltrate a military base. 

The military base can be seen as an N * N grid. Matt's target is in one of the grids and Matt is now in another grid. 

In normal case, Matt can move from a grid to one of the four neighbor grids in a second. But this mission is not easy. 

Around the military base there are fences, Matt can't get out of the base. 

There are some grids filled with obstacles and Matt can't move into these grids. 

There are also some surveillance cameras in the grids. Every camera is facing one of the four direction at first, but for every second, they will rotate 90 degree clockwisely. Every camera's sight range is 2, which means that if Matt is in the same grid as the camera, or in the grid that the camera is facing, he will be seen immediately and the mission will fail. 

Matt has a special equipment to sneak: a cardbox. Matt can hide himself in the card box and move without being noticed. But In this situation, Matt will have to use 3 seconds to move 1 grid. Matt can also just hide in the cardbox without moving. The time to hide and the time to get out of the cardbox can be ignored. 

Matt can't take the risk of being noticed, so he can't move without cardbox into a grid which is now insight of cameras or from a grid which is now insight of cameras. What's more, Matt may be in the cardbox at the beginning. 

As a live legend, Matt wants to complete the mission in the shortest time. 

Input

The first line of the input contains an integer T, denoting the number of testcases. Then T test cases follow. 

For each test cases, the first line contains one integer:N(1<=N<=500) 

In the following N lines, each line contains N characters, indicating the grids. 

There will be the following characters: 

● '.' for empty 
● '#' for obstacle 
● 'N' for camera facing north 
● 'W' for camera facing west 
● 'S' for camera facing south 
● 'E' for camera facing east 
● 'T' for target 
● 'M' for Matt

Output

For each test case, output one line "Case #x: y", where x is the case number (starting from 1) and y is the answer. 

If Matt cannot complete the mission, output '-1'.

Sample Input

2
3
M..
.N.
..T
3
M.. 
###
..T

Sample Output

Case #1: 5
Case #2: -1

题意:在一个地图里,M要达到T处,每移动一格需要一秒钟的时间(不考虑箱子),但是在地图里有很多个摄像机,摄像机的监控范围为2,即当前格和前一格,摄像机的初始状态给出(NESW),但是每秒钟摄像机都会顺时针旋转90度,若此时M的当前位置或者M想要移动的位置被摄像机发现时,M不能花费一秒的时间移动到其想要移动的位置,但是M拥有一个箱子,他可以躲在盒子里不动,或者花费三秒的时间躲在箱子里移动,求M到T的最短时间。

题解:时间优先的bfs,该提只要细心一点就能过,因为摄像机四秒钟一个循环,所以vis标记的时候可以多开一维,即vis[maxn][maxn][4],每下一次的状态有三种:

  1. 待在原地不动
  2. M的当前位置或者M想要移动的位置被摄像机发现时,花费三秒移动
  3. 不被发现时花费一秒移动

附上AC代码:

//#include"bits/stdc++.h"
//#include<unordered_map>
//#include<unordered_set>
#include<iostream>
#include<sstream>
#include<iterator>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<vector>
#include<bitset>
#include<climits>
#include<queue>
#include<iomanip>
#include<cmath>
#include<stack>
#include<map>
#include<ctime>
#include<new>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define MT(a,b) memset(a,b,sizeof(a))
#define lson l, mid, node<<1
#define rson mid + 1, r, node<<1|1
#define Root 1, m, 1
#define Node l, r, node
const int INF  =  0x3f3f3f3f;
const int O    =  1e6;
const int mod  =  20071027;
const int maxn =  5e2 + 5;
const double PI  =  acos(-1.0);
const double E   =  2.718281828459;

struct dd {
    int x, y, t;
    bool friend operator < (dd a, dd b){ return a.t > b.t; }
} st;
int run[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
int vis[maxn][maxn][4];
char c[10] = "WNES#.TM";
int mp[maxn][maxn], n;

bool check(int x, int y, int t, bool flag){
    return x<0 || x>=n || y<0 || y>=n || mp[x][y]==4 || (vis[x][y][t%4] && flag);
}

bool scan(dd node){
    if(mp[node.x][node.y] >= 0 && mp[node.x][node.y] <= 3) return true;
    for(int i=0; i<4; i++) {
        int xx = node.x + run[i][0], yy = node.y + run[i][1];
        if(check(xx, yy, node.t, false)) continue; // 因为判断四方是否有摄像机时,不需要检查vis数组,so false
        if(mp[xx][yy] > 3) continue;
        if((node.t + mp[xx][yy]) % 4 == i) return true;
    }
    return false;
}

int bfs(){
    priority_queue<dd>q; q.push(st);
    MT(vis, 0); vis[st.x][st.y][0] = 1;
    while(!q.empty()) {
        dd now = q.top(); q.pop();
        if(mp[now.x][now.y] == 6) return now.t;
        dd nex = now; nex.t ++ ;
        if(!check(nex.x, nex.y, nex.t, true)) {
            q.push(nex); vis[nex.x][nex.y][nex.t%4] = 1;
        }
        for(int i=0; i<4; i++) {
            nex = now; nex.x += run[i][0]; nex.y += run[i][1];
            if(scan(now) || scan(nex)) {
                nex.t += 3;
                if(check(nex.x, nex.y, nex.t, true)) continue;
                q.push(nex); vis[nex.x][nex.y][nex.t%4] = 1;
            }
            else {
                nex.t ++;
                if(check(nex.x, nex.y, nex.t, true)) continue;
                q.push(nex); vis[nex.x][nex.y][nex.t%4] = 1;
            }
        }
    }
    return -1;
}

int main(){
    int T, l = 0; scanf("%d", &T);
    while( T -- ){
        scanf("%d", &n);
        for(int i=0; i<n; i++) {
            char s[maxn]; scanf("%s", s);
            for(int j=0; j<n; j++) {
                for(int k=0; k<=7; k++) if(s[j] == c[k]) mp[i][j] = k;
                if(s[j] == 'M') st = {i, j, 0};
            }
        }
        int ans = bfs();
        printf("Case #%d: %d\n", ++l , ans);
    }
    return 0;
}

 代码中的时间函数:地图“WNES”(顺时针)分别标号为“0123”,以run[4][2] = {0, 1, 1, 0, 0, -1, -1, 0}顺序查找四方摄像机,当  (node.t + mp[xx][yy]) % 4 == i 时,则被发现,方法不唯一,自己画图去理解。该代码应该还可以优化一下,因为若M的当前位置或者M想要移动的位置被不被摄像机发现时,M没有必要待在原地不动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值