首页 > 代码库 > UVa 10047 独轮车

UVa 10047 独轮车

题意:独轮车均分为5个部分即五种颜色,每次前进一格恰好换一种颜色接触地面。要求从起点走到终点,但是起点时人是面向北的、绿色接触地面,终点时需要绿色接触地面、朝向哪无所谓。其中,在每个格子,有三种选择,要么前进一格,要么左转90度,要么右转90度。每种选择都是耗时一秒。

思路:将每种约束都看做一个属性,或者说一个状态由4元组决定:横坐标、纵坐标、方向、颜色。这样起始状态知道、终点状态知道,进行bfs搜索即得到最短路径。在状态转化时,有相应的三种选择,前进对应于修改横纵坐标和颜色,左转右转对应于修改方向。即三种选择都是去改变这四个属性。

讨论:这里一直局限于bfs的设置是否访问过,在想,例如图中有一个正方形的环假设为1234号4个格子,1号格子通过第一步扩展访问了2号和4号格子,假设2号格子接着走到终点时发现颜色不能是绿色着地,而事实上1号格子通过4号格子再到3号格子再到2号格子再走到终点可能是刚好绿色着地;但是1号格子先访问了2号格子后,导致不能通过4号格子到3号格子再到2号格子,因为2号格子之前访问过了!!!有这样的想法是因为还局限于每个结点是一个二维格子!!!事实上,通过上述四元组来定义一个状态,每个二维格子被拓展了,一个二维格子对应于4*5种状态!而且每个状态是唯一的,不会存在之前说的那种情况,如果一个结点不能到达终点,那么不论通过何种方式到达该结点后、从该结点出发还是不能到达终点。主要是,不能把状态空间中的结点和二维结点对应上了!

注意:实现的时候有几个错了的地方。1.取余,是%,不是 / 。总是当做模除,错过多次了。

2.看错结束条件了!结束条件是朝向无所谓的!!

3.WA的时候记得重看题目,看清题目。WA的时候记得printf合适的内容,记得先构造小数据测试下。

4.类似的这种题,都可以用定义状态、状态转换、搜索状态空间的方法试着解决。一般,最短路对应于用bfs去搜。

Code:

#include<stdio.h>
#include<string.h>

struct node
{
 int x;
 int y;
 int fx;//方向 nwse为0123 
 int clr;//颜色  green、black、red、blue、white为01234    
};

void process(int qx,int qy,int m,int n);

int dx[]={-1,0,1,0};//代表在当前方向下,前进时二维坐标将发生的变化 
int dy[]={0,-1,0,1};//比如dx[0]即代表方向0(向北)前进时x坐标的变化 

char maze[30][30];
 
int main()
{
  //freopen("10047.in","r",stdin);
  //freopen("10047.out","w",stdout);
  int m,n;
  int num=1;
  while((scanf("%d%d",&m,&n)==2)&&m&&n)
  {
    int qx,qy;
    for(int i=0;i<m;++i)
    {
      scanf("%s",maze[i]);
      for(int j=0;j<n;++j)
      {if(maze[i][j]=='S') {qx=i;qy=j;}}//起点坐标      
    }                  
    if(num!=1) printf("\n");
    printf("Case #%d\n",num++);                 
    process(qx,qy,m,n);
  }
  return 0;   
}

void process(int qx,int qy,int m,int n)
{
  struct node qs={qx,qy,0,0};
  int vis[m][n][4][5];
  memset(vis,0,sizeof(vis));
  int dist[m][n][4][5];
  memset(dist,0,sizeof(dist));
  struct node queue[4*5*30*30];
  int front=0,rear=0;
  queue[rear++]=qs;
  vis[qx][qy][0][0]=1;
  bool flag=false;
  int time=0;
  while(front<rear)
  {
    struct node hd=queue[front++];
    int x=hd.x;
    int y=hd.y;
    int fx=hd.fx;
    int clr=hd.clr;
    for(int i=0;i<3;++i)
    {
      int nx,ny,nfx,nclr;
      if(i==0)
      {//前进 
        nx=x+dx[fx];
        ny=y+dy[fx];
        nfx=fx;
        nclr=(clr+1)%5;//不是/,是%      
      }
      else if(i==1)
      {//左转90度 
        nx=x;
        ny=y;
        nfx=(fx+1)%4;
        nclr=clr;   
      }      
      else
      {//右转90度 
        nx=x;
        ny=y;
        nfx=(fx-1+4)%4;
        nclr=clr;  
      }
      
      if(nx>=0 && nx<m && ny>=0 && ny<n && !vis[nx][ny][nfx][nclr] && (maze[nx][ny]!='#'))
      {
        if(maze[nx][ny]=='T' && nclr==0)
        {
          //if((nclr==0))
          {
            vis[nx][ny][nfx][nclr]=1;
            time=dist[nx][ny][nfx][nclr]=dist[x][y][fx][clr]+1;
            flag=true;
            break;
          }                   
        }
        else
        {
          vis[nx][ny][nfx][nclr]=1;
          //printf("%d,%d,%d,%d:%d\n",nx,ny,nfx,nclr,dist[x][y][fx][clr]+1);
          dist[nx][ny][nfx][nclr]=dist[x][y][fx][clr]+1;
          struct node nnd={nx,ny,nfx,nclr};
          queue[rear++]=nnd;  
        }       
      }//if
    }//for
    if(flag) break;             
  }//while
  if(flag) printf("minimum time = %d sec\n",time);
  else printf("destination not reachable\n");   
}


UVa 10047 独轮车