说说:
这算是一道比较难的题目了,拖到今天终于搞定啦!题意是这样的,有如下这样一个棋盘:一个轮子从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;
}原文地址:http://blog.csdn.net/u011915301/article/details/39672027