题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5040
题意:给出一个棋盘图,给出起点,终点,和守卫的位置,每个守卫有东南西北的初始朝向,每个守卫的防守范围是两格(自身所在区域算一个),每过1秒钟,所有守卫的所朝方向都会顺时针旋转90度,从被监视位置到其他的任何位置都需要消耗3秒钟,从其他位置进入被监视位置需要3秒钟,其他的情况消耗1秒钟,当处于被监视位置时也可以停留若干秒,等处于非监视状态再继续,问从起点到终点的最短时间。
思路:
基本思路bfs,然后根据根据时间%4的结果,将图分成四份,每次从当前点进行扩展时,先判断当前所在点的状态是否被监视,据从再扩展到其他状态,如果处于被监视的状态,再分出一个原地不动的状态。
感觉这道题目就是要成分理解题意,然后代码敲的稳一点,姿势好一点就能A掉了。
code:
//hdu 5040 (bfs~)
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#define INF 1e9
using namespace std;
const int maxn=550;
struct ppp
{
int x,y,ti;
bool operator < (const ppp&a) const{
return ti>a.ti;
}
};
char cc[maxn][maxn];
int vis[maxn][maxn][4],N;
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}}; //up down left right
bool judge(int x,int y)
{
if(x<0||y<0||x>=N||y>=N) return false;
if(cc[x][y]=='#') return false;
return true;
}
int cal(int x,int y,int time)
{
if(cc[x][y]=='N'||cc[x][y]=='S'||cc[x][y]=='E'||cc[x][y]=='W') return 0;
for(int i=0;i<4;i++){
int mx=x+dir[i][0],my=y+dir[i][1];
if(!judge(mx,my)) continue;
if(cc[mx][my]=='N'){
//printf("N.\n");
int d=(0+time)%4;
if(abs(d-i)==2) return 1;
}
else if(cc[mx][my]=='E'){
//printf("E.\n");
int d=(1+time)%4;
if(abs(d-i)==2) return 1;
}
else if(cc[mx][my]=='S'){
//printf("S.\n");
int d=(2+time)%4;
if(abs(d-i)==2) {
//printf("S.time=%d i=%d cc=%c\n",time,i,cc[x][y]);
return 1;
}
}
else if(cc[mx][my]=='W'){
// printf("W.\n");
int d=(3+time)%4;
if(abs(d-i)==2) return 1;
}
}
return -1;
}
void bfs(int sx,int sy)
{
int ans=INF;
bool flag;
priority_queue<ppp> que;
ppp P;
P.x=sx; P.y=sy; P.ti=0;
que.push(P);
while(que.size()){
P=que.top(); que.pop();
if(cc[P.x][P.y]=='T'){
ans=min(ans,P.ti);
break;
}
for(int i=0;i<4;i++){
int mx=P.x+dir[i][0],my=P.y+dir[i][1];
if(!judge(mx,my)) continue;
ppp midP;
midP.x=mx; midP.y=my; midP.ti=P.ti;
int tt=cal(P.x,P.y,P.ti),mtt=cal(midP.x,midP.y,P.ti);
if(tt==0){
midP.ti+=3;
}
else if(tt==1){
midP.ti+=3;
ppp midP2=P;
midP2.ti++;
if(midP2.ti<vis[midP2.x][midP2.y][midP2.ti%4]){
vis[midP2.x][midP2.y][midP2.ti%4]=midP2.ti;
que.push(midP2);
}
}
else if(tt==-1){
//printf(".-1.\n");
if(mtt==0) midP.ti+=3;
else if(mtt==1){
ppp midP2=P;
midP2.ti++;
if(midP2.ti<vis[midP2.x][midP2.y][midP2.ti%4]){
vis[midP2.x][midP2.y][midP2.ti%4]=midP2.ti;
que.push(midP2);
}
midP.ti+=3;
}
else midP.ti++;
}
if(midP.ti<vis[midP.x][midP.y][midP.ti%4]){
vis[midP.x][midP.y][midP.ti%4]=midP.ti;
que.push(midP);
}
}
}
if(ans==INF) printf("-1\n");
else printf("%d\n",ans);
}
int main()
{
int T;
scanf("%d",&T);
for(int kk=1;kk<=T;kk++){
scanf("%d",&N);
for(int i=0;i<N;i++) scanf("%s",cc[i]);
for(int i=0;i<N;i++) for(int j=0;j<N;j++) for(int k=0;k<4;k++) vis[i][j][k]=INF;
printf("Case #%d: ",kk);
for(int i=0;i<N;i++){
int j;
for(j=0;j<N;j++) if(cc[i][j]=='M'){bfs(i,j);break;}
if(cc[i][j]=='M') break;
}
}
return 0;
}