HDU 5040 Instrusive

HDU 5040 Instrusive

2014 ACM/ICPC Asia RegionalBeijing Online I题

题意:给定一个N*N的矩阵,matt从M点出发要到达T点,矩阵中某些格子会有相机,首先相机有一个初始方向,之后每1秒钟顺时钟转动一次方向,如果matt走进一个正在被相机观察到的点或者matt从一个正在在相机观察的点离开的话,那么matt只能使用工具躲进里面,这样的话需要3s中移动一次,matt可以(使用工具)在某些格子停留不动,问matt从M点到达t点的最短时间是多少?

 

首先,如果直接按题意来扩展状态的话,因为每一步扩展状态的时间不同,那么必须使用优先队列加速搜索并找到最短的时间,每次只有几种情况:1、待在原地不动,时间+1。2、正在的点或要去的点正在被相机观察,则时间+3。3、不在相机视野内,则时间+1。

因此我们只需要处理好判断一个点是否在相机范围内就行了,考虑到相机的变化,那么对于每一个格子有4种状态,标记去重就行了。

这题和以前做过的hdu1180差不多是一样的…..


#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#define LL long long
#define INF 0x3f3f3f3f
#define N 510
using namespace std;
struct po{
    int x, y, time;
    po(int a, int b, int c):x(a), y(b), time(c){}
    bool operator > (const po &a) const {return time > a.time;}
};
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
char mat[N][N];
int vis[N][N][5], sx, sy, n;
inline int check(int x, int y)
{
    return x >= 0 && x < n && y >=0 && y < n && mat[x][y] != '#';
}
inline int in_camera(int x, int y, int t)
{
    if (mat[x][y] == 'N' || mat[x][y] == 'E' || mat[x][y] == 'S' || mat[x][y] == 'W') return 1;
    for (int i = 0; i < 4; i++){
        int nx = x+dx[i], ny = y+dy[i];
        if (check(nx, ny)){
            if (mat[nx][ny] == 'S' && t%4 == i%4) return 1;
            if (mat[nx][ny] == 'W' && t%4 == (i+3)%4) return 1;
            if (mat[nx][ny] == 'N' && t%4 == (i+2)%4) return 1;
            if (mat[nx][ny] == 'E' && t%4 == (i+1)%4) return 1;
        }
    }
    return 0;
}

int bfs()
{
    priority_queue<po, vector<po>, greater<po> > q;
    memset(vis, 0, sizeof(vis));
    q.push(po(sx, sy, 0));
    vis[sx][sy][0] = 1;
    while (!q.empty()){
        po t = q.top(); q.pop();
        if (mat[t.x][t.y] == 'T') return t.time;
        if (!vis[t.x][t.y][(t.time+1)%4]) q.push(po(t.x, t.y, t.time+1));
        for (int i = 0; i < 4; i++){
            int nx = t.x+dx[i], ny = t.y+dy[i];
            if (check(nx, ny)){
                if (in_camera(t.x, t.y, t.time) || in_camera(nx, ny, t.time)){
                    if (!vis[nx][ny][(t.time+3)%4]) {
                        q.push(po(nx, ny, t.time+3));
                        vis[nx][ny][(t.time+3)%4] = 1;
                    }
                }
                else {
                    if (!vis[nx][ny][(t.time+1)%4]){
                        q.push(po(nx, ny, t.time+1));
                        vis[nx][ny][(t.time+1)%4] = 1;
                    }
                }
            }
        }
    }
    return -1;
}
int main()
{
    int t, k = 0;
    scanf("%d", &t);
    while (t--){
        scanf("%d", &n);
        int flag = 1;
        for (int i = 0; i < n; i++){
            scanf("%s", mat[i]);
            for (int j = 0; j < n && flag; j++)
            if (mat[i][j] == 'M') {sx = i, sy = j; flag = 0; break;}
        }
        printf("Case #%d: %d\n", ++k, bfs());
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值