题意:独轮车均分为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");
}