独轮车(广搜状态转移的下一步伐的理解)

Problem D

独轮车

时限:1000ms 内存限制:10000K 总时限:3000ms

描述:

 

独轮车的轮子上有红、黄、蓝、白、绿(依顺时针序)5种颜色,在一个如下图所示的20*20的迷宫内每走一个格子,轮子上的颜色变化一次。独轮车只能向前推或在原地转向。每走一格或原地转向90度均消耗一个单位时间。现给定一个起点(S)和一个终点(T),求独轮车以轮子上的指定颜色到达终点所需的最短时间。

输入:

 

本题包含一个测例。测例中分别用一个大写字母表示方向和轮子的颜色,其对应关系为:E-东、S-南、W-西、N-北;R-红、Y-黄、B-蓝、W-白、G-绿。在测试数据的第一行有以空格分隔的两个整数和两个大写字母,分别表示起点的坐标S(x,y)、轮子的颜色和开始的方向,第二行有以空格分隔的两个整数和一个大写字母,表示终点的坐标T(x,y)和到达终点时轮子的颜色,从第三行开始的20行每行内包含20个字符,表示迷宫的状态。其中'X'表示建筑物,'.'表示路.

输出:

 

在单独的一行内输出一个整数,即满足题目要求的最短时间。

输入样例:

 

 

3 4 R N
15 17 Y
XXXXXXXXXXXXXXXXXXXX
X.X...XXXXXX......XX
X.X.X.....X..XXXX..X
X.XXXXXXX.XXXXXXXX.X
X.X.XX....X........X
X...XXXXX.X.XX.X.XXX
X.X.XX....X.X..X.X.X
X.X.X..XX...XXXX.XXX
X.X.XX.XX.X....X.X.X
X.X....XX.X.XX.X.X.X
X.X.X.XXXXX.XX.X.XXX
X.X.X.XXXXX....X...X
X.X.......X.XX...X.X
X.XXX.XXX.X.XXXXXXXX
X.....XX.......X...X
XXXXX....X.XXXXXXX.X
X..XXXXXXX.XXX.XXX.X
X.XX...........X...X
X..X.XXXX.XXXX...XXX
XXXXXXXXXXXXXXXXXXXX

输出样例:

 

 

56

来源:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define MAXN 210
char mapp[MAXN][MAXN];
int visit[MAXN][MAXN][6][6];
int dirx[4]={-1,1,0,0}; //上,下,左,右
int diry[4]={0,0,-1,1};
struct Node
{
	int x,y,color,dir,step;
};
queue<Node> q;
Node s,e;
int check(struct Node X)
{
	if(X.x<=0||X.x>20||X.y<=0||X.y>20||mapp[X.x][X.y]=='X'||visit[X.x][X.y][X.color][X.dir]==1)

    return 0;
    return 1;
}
int bfs()
{
	Node a,b;
	a.x=s.x,a.y=s.y,a.color=s.color,a.dir=s.dir,a.step=0;
	q.push(a);
	while(!q.empty())
	{
		a=q.front();
		q.pop();
		if(a.x==e.x&&a.y==e.y&&a.color==e.color) return a.step;  //return 是在pop的时候就return
        if(a.dir==0)
        {
            b=a; b.color=(a.color+1)%5;
            b.x=a.x-1;b.y=a.y;b.dir=a.dir;                      //step可以是step+1,也可是step+2 ,统称为下一步伐,在一些情况下,step+2可能通过广搜
            if(check(b))                                        //难找最短,要么优先队列,要么将问题转为step+1的情况
            {
                 visit[b.x][b.y][b.color][b.dir]=1;
                 b.step=a.step+1;
                 q.push(b);
            }
        }
        else if(a.dir==1)
        {
             b=a; b.color=(a.color+1)%5;
             b.x=a.x;b.y=a.y-1;b.dir=a.dir;
             if(check(b))
             {
                visit[b.x][b.y][b.color][b.dir]=1;
                b.step=a.step+1;
                q.push(b);
             }
        }
        else if(a.dir==2)
        {
            b=a; b.color=(a.color+1)%5;
            b.x=a.x+1; b.y=a.y; b.dir=a.dir;
            if(check(b))
            {
                visit[b.x][b.y][b.color][b.dir]=1;
                b.step=a.step+1;
                q.push(b);
            }
        }
        else if(a.dir==3)
        {
            b=a; b.color=(a.color+1)%5;
            b.x=a.x; b.y=a.y+1; b.dir=a.dir;
            if(check(b))
            {
                visit[b.x][b.y][b.color][b.dir]=1;
                b.step=a.step+1;
                q.push(b);
            }
        }
         b=a;  b.dir=(a.dir+1)%4;   if(check(b)) {visit[b.x][b.y][b.color][b.dir]=1; b.step=a.step+1; q.push(b);}  //原地转动不变色
         b=a;  b.dir=(a.dir-1+4)%4; if(check(b)) {visit[b.x][b.y][b.color][b.dir]=1; b.step=a.step+1; q.push(b);}
	}
	return -1; //找不到输出-1;
}
int main()
{
      int i,j;
      char a,b,c;
      scanf("%d %d %c %c",&s.x,&s.y,&a,&b);
      scanf("%d %d %c",&e.x,&e.y,&c);
      switch(a)
      {
          case 'R':s.color=0;break;
          case 'Y':s.color=1;break;
          case 'B':s.color=2;break;
          case 'W':s.color=3;break;
          case 'G':s.color=4;break;
      }
      switch(b)
      {
          case 'N':s.dir=0;break;
          case 'W':s.dir=1;break;
          case 'S':s.dir=2;break;
          case 'E':s.dir=3;break;
      }
       switch(c)
      {
          case 'R':e.color=0;break;
          case 'Y':e.color=1;break;
          case 'B':e.color=2;break;
          case 'W':e.color=3;break;
          case 'G':e.color=4;break;
      }
      for(i=1;i<=20;i++)
	  {
		  getchar();
		  for(j=1;j<=20;j++)
          scanf("%c",&mapp[i][j]);
	  }
	  memset(visit,0,sizeof(visit));
	  visit[s.x][s.y][s.color][s.dir]=1;
	  int ans=bfs();
	  printf("%d\n",ans);
	  return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值