首页 > 代码库 > 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 独轮车