2014 ACM/ICPC Asia Regional Beijing Online
对于N*N的矩阵
M起点,T终点
有起始方向分别向北N,东E,南S,西W的摄像头,可以检测的范围为自己+所指方向1格,每1秒顺时针旋转90°
前面有灯或者自己站的地方有灯,移动需要花3秒,或者原地等一秒。
BFS优先队列
开3维 hash数组判重,第三维是在该点等待的时间,开到4即可(摄像头转一圈)
对图中的每个点提前处理处会在什么时候被摄像头看到,用2进制压缩存储在MAP数组中
然后常规BFS解决
比赛时候手残没写CASE。。。。找了半天错误。。。。。
/*
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\ = /O
____/`---'\____
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||- \
| | \\\ - /// | |
| \_| ''\---/'' | |
\ .-\__ `-` ___/-. /
___`. .' /--.--\ `. . __
."" '< `.___\_<|>_/___.' >'"".
| | : `- \`.;`\ _ /`;.`/ - ` : | |
\ \ `-. \_ __\ /__ _/ .-` / /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fozubaoyou pass System Test!
*/
#include "stdio.h"
#include "string.h"
#include "queue"
using namespace std;
int inf=0x3f;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct node
{
int x,y,step,wait; // step记录步数,wait记录等待的时间
friend bool operator<(node n1,node n2)
{
return n1.step>n2.step;
}
};
int s_x,s_y,n;
int b[5];
char str[510][510];
int map[510][510],hash[510][510][5]; // MAP 存储每个点什么时候会被看到,HASH判重第三维是在该点等待的时间
int bfs()
{
priority_queue<node>q;
node cur,next;
int i,time;
cur.x=s_x;
cur.y=s_y;
cur.step=0;
cur.wait=0;
q.push(cur);
memset(hash,inf,sizeof(hash));
hash[cur.x][cur.y][0]=0;
while (!q.empty())
{
cur=q.top();
q.pop();
if (str[cur.x][cur.y]=='T') return cur.step;
for (i=0;i<4;i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
if (next.x<0 || next.x>=n || next.y<0 || next.y>=n) continue;
if (str[next.x][next.y]=='#') continue;
time=b[cur.step%4];
if ((map[cur.x][cur.y]&time)==time || (map[next.x][next.y]&time)==time) // 当前点或下一个点会被看到
next.step=cur.step+3;
else
next.step=cur.step+1;
next.wait=0;
if (next.step<hash[next.x][next.y][next.wait])
{
q.push(next);
hash[next.x][next.y][next.wait]=next.step;
}
}
next.x=cur.x;
next.y=cur.y;
next.step=cur.step+1;
next.wait=cur.wait+1;
if (next.wait<=3 && next.step<hash[next.x][next.y][next.wait]) // 原地等待
{
q.push(next);
hash[next.x][next.y][next.wait]=next.step;
}
}
return -1;
}
int main()
{
int Case,ii,i,j;
scanf("%d",&Case);
b[0]=1; b[1]=2; b[2]=4; b[3]=8;
for (ii=1;ii<=Case;ii++)
{
scanf("%d",&n);
getchar();
for (i=0;i<n;i++)
gets(str[i]);
printf("Case #%d: ",ii);
memset(map,0,sizeof(map));
for (i=0;i<n;i++) // 状压存储每个点什么时候会被看到
for (j=0;j<n;j++)
{
if (str[i][j]=='M') { s_x=i; s_y=j;}
if (str[i][j]=='N')
{
map[i][j]=15;
if (i-1>=0) map[i-1][j]|=1;
if (j+1<n) map[i][j+1]|=2;
if (i+1<n) map[i+1][j]|=4;
if (j-1>=0) map[i][j-1]|=8;
}
if (str[i][j]=='E')
{
map[i][j]=15;
if (j+1<n) map[i][j+1]|=1;
if (i+1<n) map[i+1][j]|=2;
if (j-1>=0) map[i][j-1]|=4;
if (i-1>=0) map[i-1][j]|=8;
}
if (str[i][j]=='S')
{
map[i][j]=15;
if (i+1<n) map[i+1][j]|=1;
if (j-1>=0) map[i][j-1]|=2;
if (i-1>=0) map[i-1][j]|=4;
if (j+1<n) map[i][j+1]|=8;
}
if (str[i][j]=='W')
{
map[i][j]=15;
if (j-1>=0) map[i][j-1]|=1;
if (i-1>=0) map[i-1][j]|=2;
if (j+1<n) map[i][j+1]|=4;
if (i+1<n) map[i+1][j]|=8;
}
}
printf("%d\n",bfs());
}
return 0;
}