獨輪車(廣搜狀態轉移的下一步伐的理解)
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; }