HDU 4375 Programmable Robot [搜索]

  给出一个N*M的矩阵,其中有些格子不可走。一个机器人想要通过命令从起点走到终点,命令分为三种,左转右转和前进,先给出一个只包含左转和右转的指令序列,问是否能够通过增加有限个的前进指令,使该指令可以完成从起点到终点。

  N和M的范围是1000,指令长度为1000000,必然有巧妙的方法。

  首先,执行完每个命令的朝向肯定是固定的,所以如果能更早的到达某一个格子的某个方向,必然会选择最早的到达方法,问题转化为求最早到达d[x][y][d]这个状态所需要的指令数。这里可以看作最短路的问题,用一个优先队列来解决,但是每次选择是LogN的。

  有更优的方法在O(1)的复杂度实现选择,处理出每个命令下一次朝向某个方向至少要执行到之后的哪一条命令,然后对每条指令拉一个链表,转移到这条指令的格子就在这放在这条指令的后面,依次执行每一条指令,就能求出所有到达d[x][y][d]的最小指令数。

  

 1 #include <string.h>
 2 #include <stdio.h>
 3 #define MAXN 1005
 4 #define MAXN2 1000005
 5 #define INF 0x3f3f3f3f
 6 struct pnt{
 7     int x, y, n;
 8 }st, en, e[MAXN2*4];
 9 int cas = 0, n, w, h;
10 int first[MAXN2], es;
11 int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
12 char mz[MAXN][MAXN], str[MAXN2];
13 int nextd[MAXN2][4], dir[MAXN2], forw[4], vis[MAXN][MAXN][4];
14 void addedge(int u, int x, int y){
15     e[es].x = x, e[es].y =y, e[es].n = first[u], first[u] = es++;
16 }
17 bool push(int s, int x, int y, int d){
18     while (x>=0&&y>=0&&x<h&&y<w&&mz[x][y]!='#'&&vis[x][y][d]!=cas) {
19         if (x == en.x && y == en.y) return 1;
20         vis[x][y][d] = cas;
21         addedge(s, x, y);
22         x += dx[d], y += dy[d];
23     }
24     return 0;
25 }
26 bool bfs(){
27     memset(first, -1, 4 * n + 4), es = 0;
28     if (push(0, st.x, st.y, 0)) return 1;
29     for (int i = 0 ;i <= n; i++)
30         for (int j = first[i]; j != -1; j = e[j].n)
31             for (int k = 0; k < 4; k++)
32                 if (nextd[i][k] != INF && push(nextd[i][k], e[j].x, e[j].y , k)) return 1;
33     return 0;
34 }
35 void init(){
36     dir[0] = 0;
37     for (int i = 0; i < n; i++){
38         if (str[i] == 'L')dir[i+1] = (dir[i] + 3) % 4;
39         else dir[i+1] = (dir[i] + 1) % 4 ;
40     }
41     forw[0] = forw[1] = forw[2] = forw[3] = INF;
42     for (int i = n; i >= 0; i--){
43         for (int j = 0; j < 4; j++)
44             nextd[i][j] = forw[j];
45         forw[dir[i]] = i;
46     }
47 }
48 int main(){
49     //freopen("test.in", "r", stdin);
50     while (scanf("%d%d%d", &h, &w, &n) != EOF) {
51         cas++;
52         scanf("%s", str);
53         for (int i = 0; i < h; i++) {
54             scanf("%s", mz[i]);
55             for (int j = 0; j < w; j++) {
56                 if (mz[i][j] == 'S')st.x = i, st.y = j;
57                 if (mz[i][j] == 'E')en.x = i, en.y = j;
58             }
59         }
60         init();
61         printf("%s\n", bfs()?"Yes":"No");
62     }
63     return 0;
64 }
原文地址:https://www.cnblogs.com/swm8023/p/2725197.html