1.12 POJ 1376 Robot
http://poj.org/problem?id=1376
今天本来看了下循环赛算法,准备在oj上搜下看有木有相关的题,结果发现貌似木有。。
所以找出一道以前数算实习课上的水题来做。
其实也不是特别水,有些细节还是要注意的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 const int MAXN = 60; 5 int r, c, ex, ey, mx[4] = {-1, 0, 1, 0}, my[4] = {0, 1, 0, -1}; 6 bool m[MAXN][MAXN], vis[MAXN][MAXN][4]; 7 struct Node{ 8 int x, y, dir, tim; 9 }q[100010]; int head, tail; 10 11 int main() 12 { 13 // freopen("input", "r", stdin); 14 char str[10]; 15 while(scanf("%d %d", &r, &c), r && c) 16 { 17 memset(vis, 0, sizeof(vis)); 18 memset(m, 1, sizeof(m)); 19 head = 0, tail = 1; 20 for(int i=1 ; i<=r ; i++) 21 for(int j=1 ; j<=c ; j++) 22 { 23 int tmp; 24 scanf("%d", &tmp); 25 m[i][j] = tmp; 26 if(m[i][j]) 27 m[i][j-1] = m[i-1][j] = m[i-1][j-1] = 1; 28 if(i == r || j == c) 29 m[i][j] = 1; 30 } 31 scanf("%d %d %d %d %s", &q[0].x, &q[0].y, &ex, &ey, str); 32 switch(str[0]) 33 { 34 case 'n':q[0].dir = 0; break; 35 case 'e':q[0].dir = 1; break; 36 case 's':q[0].dir = 2; break; 37 case 'w':q[0].dir = 3; break; 38 default: printf("ha?\n"); exit(1); 39 } 40 while(head != tail) 41 { 42 if(q[head].x == ex && q[head].y == ey) 43 { 44 printf("%d\n", q[head].tim); 45 break; 46 } 47 for(int k=1 ; k<=3 ; k++) 48 { 49 q[tail].x = q[head].x + mx[q[head].dir] * k; 50 q[tail].y = q[head].y + my[q[head].dir] * k; 51 q[tail].dir = q[head].dir; 52 q[tail].tim = q[head].tim + 1; 53 if(m[q[tail].x][q[tail].y]) 54 break; 55 if(!vis[q[tail].x][q[tail].y][q[tail].dir]) 56 { 57 vis[q[tail].x][q[tail].y][q[tail].dir] = 1; 58 tail++; 59 } 60 } 61 for(int k=1 ; k<=2 ; k++) 62 { 63 q[tail] = q[head]; 64 q[tail].tim++, q[tail].dir = (q[head].dir + k*2 - 1) % 4; 65 if(!vis[q[tail].x][q[tail].y][q[tail].dir]) 66 { 67 vis[q[tail].x][q[tail].y][q[tail].dir] = 1; 68 tail++; 69 } 70 } 71 head++; 72 } 73 if(head == tail) printf("-1\n"); 74 } 75 }
一开始以为需要用Astar,但是先上网大概看了下别人的思路发现只要简单BFS就可以,于是果断水之。
跟裸BFS搜地图的区别有三:
1. 机器人有直径。所以我们保存的是网格中的交点,而不是面。对一个输入的面来说,它的四个点应设置为机器人不可达的(第27行)。且四周边界设置为均不可达(第18,28行)。这样在判断时无需进行边界处理,只需看m可不可达。
2. 可以一次向前走多步,这点很好处理,乘一个步数就可以了。
3. 还可以向左向右转,也算一个时间点。所以要设置方向域。并且在vis数组中也要设置方向域判重。