题意:M是起点,T是终点,‘.'是路,‘#’是墙,中间有很多摄像头都有初始的方向,而且每隔一秒钟要顺时针转90度,被照到的时候有两种选择,可以原地不动,也可以用三秒走一个格子,问你从起点到终点的最短时间,如果不能到达输出-1.
思路:如果当前点和要走的点都是通路,如果被照到了,那就原地不动或者是在盒子里面走(要用三秒),这样我们可以知道我们最多在原地等三秒,要不就不是最优的了,如果前面是灯就只有花三秒走过去了,这道题要注意的是不能用普通的状态来保存,因为走过的点不一定就是最优的,所以我们要另外开一个二维数组来保存当前位置最短的时间,这样来标记状态,还有就是要用优先队列,因为走一个格子的时间不是相同的。
AC代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=510;
const int inf=1<<29;
int xx[4]={0,0,-1,1},yy[4]={-1,1,0,0};
int n,t,mx,my,tx,ty;
char Map[maxn][maxn];
int d[maxn][maxn];
struct node
{
int x;
int y;
int step;
bool operator<(const node &p) const
{
return step>p.step;
}
}m,nxt;
int check(int x,int y)
{
if(x<0||y<0||x>=n||y>=n)
return 1;
return 0;
}
int lpf(int x,int y,int time)
{
if(Map[x][y]!='.')
return 0;
if(x-1>=0)
{
if(time==0&&Map[x-1][y]=='S')
return 0;
else if(time==1&&Map[x-1][y]=='E')
return 0;
else if(time==2&&Map[x-1][y]=='N')
return 0;
else if(time==3&&Map[x-1][y]=='W')
return 0;
}
if(x+1<n)
{
if(time==0&&Map[x+1][y]=='N')
return 0;
else if(time==1&&Map[x+1][y]=='W')
return 0;
else if(time==2&&Map[x+1][y]=='S')
return 0;
else if(time==3&&Map[x+1][y]=='E')
return 0;
}
if(y-1>=0)
{
if(time==0&&Map[x][y-1]=='E')
return 0;
else if(time==1&&Map[x][y-1]=='N')
return 0;
else if(time==2&&Map[x][y-1]=='W')
return 0;
else if(time==3&&Map[x][y-1]=='S')
return 0;
}
if(y+1<n)
{
if(time==0&&Map[x][y+1]=='W')
return 0;
else if(time==1&&Map[x][y+1]=='S')
return 0;
else if(time==2&&Map[x][y+1]=='E')
return 0;
else if(time==3&&Map[x][y+1]=='N')
return 0;
}
return 1;
}
int bfs()
{
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
d[i][j]=inf;
priority_queue<node> q;
q.push(m);
d[m.x][m.y]=0;
while(!q.empty())
{
m=q.top();
q.pop();
if(m.x==tx&&m.y==ty)
return m.step;
for(int i=0;i<4;i++)
{
nxt.x=m.x+xx[i];
nxt.y=m.y+yy[i];
nxt.step=m.step+1;
if(check(nxt.x,nxt.y))
continue;
if(Map[nxt.x][nxt.y]=='#')
continue;
if(Map[nxt.x][nxt.y]=='.')
{
int flag=0;
for(int j=0;j<3;j++) //最多等三秒
{
int time=(m.step+j)%4;
if(lpf(m.x,m.y,time)&&lpf(nxt.x,nxt.y,time)&&nxt.step+j<d[nxt.x][nxt.y]) //如果两个点都没被照到
{
nxt.step+=j;
d[nxt.x][nxt.y]=nxt.step;
q.push(nxt);
flag=1;
break;
}
}
if(!flag)
{
nxt.step+=2;
if(nxt.step<d[nxt.x][nxt.y])
{
d[nxt.x][nxt.y]=nxt.step;
q.push(nxt);
}
}
}
else
{
nxt.step+=2;
if(nxt.step<d[nxt.x][nxt.y])
{
d[nxt.x][nxt.y]=nxt.step;
q.push(nxt);
}
}
}
}
return -1;
}
int main()
{
scanf("%d",&t);
for(int k=1;k<=t;k++)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",Map[i]);
for(int j=0;j<n;j++)
{
if(Map[i][j]=='M')
{
m.x=i;
m.y=j;
m.step=0;
Map[i][j]='.';
}
else if(Map[i][j]=='T')
{
tx=i;
ty=j;
Map[i][j]='.';
}
}
}
printf("Case #%d: %d\n",k,bfs());
}
return 0;
}