说说:
这算是一道比较难的题目了,拖到今天终于搞定啦!题意是这样的,有如下这样一个棋盘:一个轮子从S出发开始运动,它有三个选择,沿原方向向前滚一格,或者在原地向左或向右转90度,并且无论是滚动还是转身都将耗时一秒。其中轮子由五种颜色组成,每滚动一个,与地面接触的颜色都将变换一次,如下图所示。假设开始的时候轮子停在S初,方向朝北,颜色为绿色,则能否到达目的地T,且颜色仍旧为绿色,求最短时间。
分析:开始的时候想法非常简单,就是DFS嘛,看能不能到达T,到时候再看看颜色的状态都差不多了。其实这是不对的,因为它很有可能在第一次到达T的时候,颜色状态是不对的,然后说不定去绕了一圈之后就对了。因为并没有规定,不能重复经过一个节点。这样的话就比较麻烦了。最后经过刘汝佳的《算法竞赛训练指南》里的提示,才发行应该将轮子所处的位置,颜色,方向合起来定义为一个状态才是合理的。因为这样才是唯一的。因此,有了这个想法之后,然后简单的用一下BFS问题就解决了。
源代码:
#include <stdio.h> #include <string.h> #define MAX 25+5 typedef struct { int x; int y; int color; int dir; int time; }NODE; NODE queue[20000]; int M,N,sx,sy,ans,front,rear; char maze[MAX][MAX]; char vis[MAX][MAX][5][4];//标记状态是否被访问 int bfs(int,int,int,int,int); int inqueue(int,int,int,int,int);//将状态加入队列 int main(){ int i,j,T=1; //freopen("data","r",stdin); while(scanf("%d%d",&M,&N)){ if(M==0&&N==0) break; else if(T>1) putchar('\n'); for(i=0;i<M;i++) scanf("%s",maze[i]); for(i=0;i<M;i++) for(j=0;j<N;j++) if(maze[i][j]=='S') sx=i,sy=j; memset(vis,0,sizeof(vis)); front=rear=0; printf("Case #%d\n",T++); if(bfs(sx,sy,0,0,0)) printf("minimum time = %d sec\n",ans); else printf("destination not reachable\n"); } return 0; } int bfs(int x,int y,int dir,int color,int time){ int val; inqueue(x,y,dir,color,time); while(front<rear){ if(inqueue(queue[front].x,queue[front].y,(queue[front].dir+1)%4,queue[front].color,queue[front].time+1)) return 1;//往一个方向转动 if(inqueue(queue[front].x,queue[front].y,(queue[front].dir+3)%4,queue[front].color,queue[front].time+1)) return 1;//往另一个方向转动 switch(queue[front].dir){//根据当前的方向移动一格 case 0: val=inqueue(queue[front].x-1,queue[front].y,queue[front].dir,(queue[front].color+1)%5,queue[front].time+1); break; case 1: val=inqueue(queue[front].x,queue[front].y+1,queue[front].dir,(queue[front].color+1)%5,queue[front].time+1); break; case 2: val=inqueue(queue[front].x+1,queue[front].y,queue[front].dir,(queue[front].color+1)%5,queue[front].time+1); break; case 3: val=inqueue(queue[front].x,queue[front].y-1,queue[front].dir,(queue[front].color+1)%5,queue[front].time+1); break; } if(val) return 1; front++; } return 0; } int inqueue(int x,int y,int dir,int color,int time){//将状态加入队列 if(x<0||x>=M||y<0||y>=N||vis[x][y][color][dir]||maze[x][y]=='#') return 0; else if(maze[x][y]=='T'&&color==0){ ans=time; return 1; } vis[x][y][color][dir]=1; queue[rear].x=x; queue[rear].y=y; queue[rear].dir=dir; queue[rear].color=color; queue[rear].time=time; rear++; return 0; }
时间: 2024-11-07 19:50:59