2014北京网络赛09题,hdu 5040
这次网络赛真是惨,也怪做题策略没想好,当时切完签到题之类的水题之后,马上就去看06青蛙那题去了。结果被那只死青蛙给坑惨了T_T。。。搞了四小时没搞出来...跪给那只青蛙了。。。本来当时是准备要做这道题的,题目描述也是好蛋疼,有人说这题不如直接去看Clarification,不看题目了,这也说明这题题目描述确实不清晰,虽然没这么夸张,题目还是得看的。
重新看这道题,不是很难,最短时间的话,那当然想到BFS,纯BFS的话,只是最短步数,所以我们需要+优先队列。状态的话,只需要坐标(x,y)还有时间cur_t%4这三个元素就行了。
解释一下为什么是cur_t%4,仔细想想会发现,这一题每个状态之间的不同点,除了当前位置的坐标,还有所有监视器的转向,而这个转向是以4为周期的没错吧,所以,只要某两个状态的坐标相同,且t%4也相同的话,那么这就是一个状态,压进队列一次就不用再压第二次了。除了这一点,其他应该没什么难点。后来写了一份代码,一炮就过了。。T_T为什么当时没先做这个?
代码:
#include <iostream> #include <cstdio> #include <queue> #include <cstring> #include <algorithm> #define N 511 using namespace std; int n,dir[4][2]={{0,-1},{-1,0},{0,1},{1,0}};//E==0,S==1,W==2,N==3 int change[110]; bool vis[N][N][5]; char a[N][N]; struct node { int x,y,t; node(){;} //构造函数 node(int xx,int yy,int tt){x=xx,y=yy,t=tt;}//构造函数 bool operator<(const node s)const{return t>s.t;} }; int check(int x,int y,int t)//return 1代表该位置当前被灯照到,2代表当前位置没有灯照射,也可以走,0代表不可达 { if(x<1||x>n||y<1||y>n||a[x][y]=='#') return 0; if(change[a[x][y]]!=-1) return 1; for(int i=0;i<4;i++)//要知道当前点有没有被照到,需要查看当前点四个方向上有没有灯朝向这个点 { int xx=x+dir[i][0],yy=y+dir[i][1]; if(xx<1||xx>n||yy<1||yy>n) continue; int tmp=change[a[xx][yy]];//tmp>=0代表当前点有灯 if(tmp>=0&&(tmp+t)%4==i) return 1; //(tmp+t)代表当前时间,%4代表此时灯的转向,稍微设计了一下方向函数dir,使得(tmp+t)==i的时候,说明该点被照到 } return 2; } int bfs(int sx,int sy) { memset(vis,0,sizeof(vis)); priority_queue<node> que; que.push(node(sx,sy,0)); while(!que.empty()) { node tmp=que.top();que.pop(); if(a[tmp.x][tmp.y]=='T') return tmp.t; int cur_t; //不移动的情况 cur_t=tmp.t+1; if(!vis[tmp.x][tmp.y][cur_t%4]) vis[tmp.x][tmp.y][cur_t%4]=1,que.push(node(tmp.x,tmp.y,cur_t)); int flag=check(tmp.x,tmp.y,tmp.t);//flag=1说明当前点被照亮 for(int i=0;i<4;i++) { int cx=tmp.x+dir[i][0],cy=tmp.y+dir[i][1]; int che=check(cx,cy,tmp.t); if(che==0) continue; if(che==1||flag==1) cur_t=tmp.t+3;//要移动的点或者当前点被照亮 else if(che==2) cur_t=tmp.t+1; if(!vis[cx][cy][cur_t%4]) vis[cx][cy][cur_t%4]=1,que.push(node(cx,cy,cur_t)); } } return -1; } int main() { #ifndef ONLINE_JUDGE freopen("D:/in.txt","r",stdin); #endif // ONLINE_JUDGE memset(change,-1,sizeof(change)); change['E']=0,change['S']=1,change['W']=2,change['N']=3; int T,cas=1; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%s",a[i]+1); int sx,sy; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(a[i][j]=='M') sx=i,sy=j; int ans=bfs(sx,sy); printf("Case #%d: %d\n",cas++,ans); } return 0; }
原文地址:http://blog.csdn.net/u013912596/article/details/39478031