hdu 5040 Instrusive

时间:2023-03-09 05:00:37
hdu 5040 Instrusive

Instrusive

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

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
Source
题意:一张图,给出起点终点,障碍物以及摄像头,摄像头每秒钟转90度,求到达终点的最短时间。
思路:一开始想着建立500*500*4,用spfa,常数写搓果断TLE,后来改2m步后自动break,涉险400ms过关。后来发现×4的状态可以去掉,改完之后去掉break优化700ms。再改用优先队列,170ms。再改用各种方法,都没有能在170ms内跑完的。尽力了,不改了。下面贴代码。
 /*
* Author: Joshua
* Created Time: 2014年09月21日 星期日 14时19分18秒
* File Name: 1009.cpp
*/
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 520
#define inf 0x7f7f7f7f
typedef long long LL;
int T,n,sx,sy,ex,ey,kase;
char map[maxn][maxn];
int dir[][]={{-,},{,},{,},{,-}};
int ce[maxn][maxn];
int xm=;
int d[maxn*maxn];
bool f[maxn*maxn]; struct cmp
{
bool operator()(int a,int b)
{
return d[a]>d[b]; }
}; void init()
{
scanf("%d",&n); scanf ("\n");
for (int i=;i<n;++i)
memset(ce[i],-,*n);
for (int i=;i<n;++i)
{
scanf("%s",map[i]);
for (int j=;j<n;++j)
{
if (map[i][j]=='M') sx=i,sy=j,map[i][j]='.';
if (map[i][j]=='T') ex=i,ey=j,map[i][j]='.';
if (map[i][j]=='N') ce[i][j]=,map[i][j]='.';
if (map[i][j]=='E') ce[i][j]=,map[i][j]='.';
if (map[i][j]=='S') ce[i][j]=,map[i][j]='.';
if (map[i][j]=='W') ce[i][j]=,map[i][j]='.';
}
}
int temp;
if (n<=)
{
for (int i=;i<n;++i)
for (int j=;j<n;++j)
{
temp=(i<<)+j;
d[temp]=inf;
f[temp]=false;
}
}
else
{
memset(d,0x7f,sizeof(d));
memset(f,,sizeof(f));
}
} void update(int x,int y,int dir,priority_queue<int, vector<int>,cmp> &q)
{
int temp=(x<<)+y;
if (d[temp]>dir)
{
d[temp]=dir;
q.push(temp);
}
} inline int fabs(const int &x)
{
if (x< ) return -x;
return x;
} bool find(int tx,int ty,int tt )
{
int xx,yy;
if (~ce[tx][ty]) return true;
for (int i=;i<;++i)
{
xx=tx+dir[i][];
yy=ty+dir[i][];
if (xx< || xx>=n || yy< || xx>=n) continue;
if (!(~ce[xx][yy])) continue;
if ( fabs( ((ce[xx][yy]+tt)&)-i)==) return true;
}
return false;
} void solve()
{
int temp,tx,ty,tt,xx,yy,dis,end=(ex<<)+ey;
bool flag;
priority_queue<int,vector<int>,cmp> q;
update(sx,sy,,q);
while (!q.empty())
{
temp=q.top();
q.pop();
if (f[temp]) continue;
if (temp==end) break;
f[temp]=true;
tx=(temp>>)&xm;
ty=temp&xm;
dis=d[temp];
tt=dis&;
for (int i=;i<;++i)
{
flag=find(tx,ty,tt+i);
for (int l=;l<;++l)
{
xx=tx+dir[l][];
yy=ty+dir[l][];
if (xx< || xx>=n || yy< || yy>=n) continue;
if (map[xx][yy]=='#') continue;
if (flag || find(xx,yy,tt+i)) update(xx,yy,dis+i+,q);
else update(xx,yy,dis++i,q);
}
}
}
int ans=inf;
if (d[end]<ans)
ans=d[end];
if (ans==inf) ans=-;
printf("Case #%d: %d\n",kase,ans);
} int main()
{
scanf("%d",&T);
kase=;
while (T--)
{
kase++;
init();
solve();
}
return ;
}