首页 > 代码库 > The Monocycle UVA 10047

The Monocycle UVA 10047

说说:

这算是一道比较难的题目了,拖到今天终于搞定啦!题意是这样的,有如下这样一个棋盘:一个轮子从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;
}


The Monocycle UVA 10047