hdu5040(bfs,优先队列)

202 篇文章 0 订阅
154 篇文章 0 订阅

Instrusive

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1578    Accepted Submission(s): 467


Problem Description
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

题意:

告诉一副地图:一个起点,一个终点,若干墙,若干监视器,剩下的是空地。

起点,终点,监视器都算空地。

监视器初始值会指定一个方向,共有四个方向。

监视器每秒顺时针转动到下个方向。

监视器视野距离为2(不知道为什么要说是2。。。故意迷惑人的T_T).

在监视器的位置或在监视器面向的格子是监视区域。

普通的移动一格需要消耗1秒时间。

在监视器下移动一格需要消耗3秒时间。

如果呆在原地不动,即使在监视器视野内也不会被发现。

 

求最少时间从起点到达终点。

不能到达输出-1。

思路:从一个点到另一个点的话,任意一个点都被照到的话都不能直接走。所以对于任一个目标点,如果有灯就直接躲盒子里走,如果是空地,就最多等三秒。

其实感觉有点坑。。怎么写都wa。。。刚开始思索着直接走的过程是前一秒在初始格子不被灯照着,后一秒在下一步走到的格子也不被灯照着的情况就是能直接走过去了,结果看了看人家的代码意思是走到另一个格子的那个时间点两个格子同时不被灯照着,仔细想想确实也对,能走就走,如果第一秒两个格子都不被照着那么第一秒肯定就能走了,所以如果等到第二秒的时候,首先肯定的就是第一秒走不了,所以我刚开始的担忧其实是错误的。。。。无语


#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;
typedef long long ll;
const int INF=999999999;
char a[505][505];
int vis[505][505];///记录每个位置上的最短时间
int fx[4][2]= {{-1,0},{1,0},{0,-1},{0,1}};///方向数组
struct data
{
    int x,y,t;
    bool operator<(const data &p)const
    {
        return t>p.t;
    }
} bj;
int n;
bool cmp(int x0,int y0,int t)///判断某个点是否被灯照着
{
    t--;
    if(a[x0][y0]=='W'||a[x0][y0]=='E'||a[x0][y0]=='N'||a[x0][y0]=='S')return 0;
    for(int i=0; i<4; i++)
    {
        int xx=x0+fx[i][0],yy=y0+fx[i][1];
        if(xx>=0&&xx<n&&yy>=0&&yy<n)
        {
            if(i==0)
            {
                if(t%4==0&&a[xx][yy]=='S')
                    return 0;
                else if(t%4==1&&a[xx][yy]=='E')
                    return 0;
                else if(t%4==2&&a[xx][yy]=='N')
                    return 0;
                else if(t%4==3&&a[xx][yy]=='W')
                    return 0;
            }
            else if(i==1)
            {
                if(t%4==0&&a[xx][yy]=='N')
                    return 0;
                else if(t%4==1&&a[xx][yy]=='W')
                    return 0;
                else if(t%4==2&&a[xx][yy]=='S')
                    return 0;
                else if(t%4==3&&a[xx][yy]=='E')
                    return 0;
            }
            else if(i==2)
            {
                if(t%4==0&&a[xx][yy]=='E')
                    return 0;
                else if(t%4==1&&a[xx][yy]=='N')
                    return 0;
                else if(t%4==2&&a[xx][yy]=='W')
                    return 0;
                else if(t%4==3&&a[xx][yy]=='S')
                    return 0;
            }
            else
            {
                if(t%4==0&&a[xx][yy]=='W')
                    return 0;
                else if(t%4==1&&a[xx][yy]=='S')
                    return 0;
                else if(t%4==2&&a[xx][yy]=='E')
                    return 0;
                else if(t%4==3&&a[xx][yy]=='N')
                    return 0;
            }
        }
    }
    return 1;
}

int dx,dy;
int bfs(int x0,int y0)
{
    priority_queue<data>q;
    bj.x=x0,bj.y=y0,bj.t=0;
    q.push(bj);
    vis[x0][y0]=0;
    while(!q.empty())
    {
        data tt=q.top();
        q.pop();
        int x=tt.x,y=tt.y,t=tt.t;
        if(x==dx&&y==dy)
            return t;
        for(int i=0; i<4; i++)
        {
            int xx=x+fx[i][0],yy=y+fx[i][1];
            if(xx>=0&&xx<n&&yy>=0&&yy<n&&a[xx][yy]!='#')
            {
                if(a[xx][yy]=='.')
                {
                    if(cmp(x,y,t+1)&&cmp(xx,yy,t+1)&&t+1<vis[xx][yy])///重点就在这里,首先判断不等是否可以走
                        tt.x=xx,tt.y=yy,tt.t=t+1,q.push(tt),vis[xx][yy]=t+1;
                    else if(cmp(x,y,t+2)&&cmp(xx,yy,t+2)&&t+2<vis[xx][yy])///在判断等1秒是否能走
                        tt.x=xx,tt.y=yy,tt.t=t+2,q.push(tt),vis[xx][yy]=t+2;
                    else if(t+3<vis[xx][yy])///最后就算等了2秒,再加上走过去花费时间1秒,也就相当于躲在盒子里面走过去3秒,再多等也没意义了,这是实在等不了了直接躲在盒子里面过去了
                        tt.x=xx,tt.y=yy,tt.t=t+3,q.push(tt),vis[xx][yy]=t+3;
                }
                else if(t+3<vis[xx][yy])///这里表示该位置本身就是一个灯,所以直接躲在盒子里面走
                    tt.x=xx,tt.y=yy,tt.t=t+3,q.push(tt),vis[xx][yy]=t+3;
            }
        }
    }
    return -1;
}

int main()
{
    int t,o=1;
    scanf("%d",&t);
    while(t--)
    {
        int x,y;
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
            {
                vis[i][j]=INF;
                scanf(" %c",&a[i][j]);
                if(a[i][j]=='M')
                    a[i][j]='.',x=i,y=j;
                else if(a[i][j]=='T')
                    a[i][j]='.',dx=i,dy=j;
            }
        printf("Case #%d: %d\n",o++,bfs(x,y));
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值