• POJ 3984 迷宫问题 (Dijkstra)


    迷宫问题

    Description
    定义一个二维数组:
    int maze[5][5] = {
    0, 1, 0, 0, 0,
    0, 1, 0, 1, 0,
    0, 0, 0, 0, 0,
    0, 1, 1, 1, 0,
    0, 0, 0, 1, 0,
    };
    它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到
    右下角的最短路线。

    Input
    一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

    Output
    左上角到右下角的最短路径,格式如样例所示。

    Sample Input
    0 1 0 0 0
    0 1 0 1 0
    0 0 0 0 0
    0 1 1 1 0
    0 0 0 1 0

    Sample Output
    (0, 0)
    (1, 0)
    (2, 0)
    (2, 1)
    (2, 2)
    (2, 3)
    (2, 4)
    (3, 4)
    (4, 4)

    解决方案:

    对于这题,我们可以把它maze数组转化为一个图,不能通过的话,即两点之间无路径,然后利用Dijkstra算法寻找S点到T点的最短路径。

    Dijkstra算法可参考维基百科迪科斯彻算法,其核心代码如下:

     1 function Dijkstra(G, w, s)
     2      for each vertex v in V[G]                        // 初始化
     3            d[v] := infinity                           // 将各点的已知最短距离先设置成无穷大
     4            previous[v] := undefined                   // 各点的已知最短路径上的前趋都未知
     5      d[s] := 0                                        // 因为出发点到出发点间不需移动任何距离,所以可以直接将s到s的最小距离设为0
     6      S := empty set
     7      Q := set of all vertices
     8      while Q is not an empty set                      // Dijkstra演算法主體
     9            u := Extract_Min(Q)
    10            S.append(u)
    11            for each edge outgoing from u as (u,v)
    12                   if d[v] > d[u] + w(u,v)             // 拓展边(u,v)。w(u,v)为从u到v的路径长度。
    13                         d[v] := d[u] + w(u,v)         // 更新路径长度到更小的那个和值。
    14                         previous[v] := u              // 记录前趋顶点

    对于上图,我们的算法可以大大简化,因为每条路径的权重都相等,由于Dijkstra是按照广度优先搜索来进行遍历的,因而在我们这,先到达这个点的路径即为最短路径(这里对照上图,在纸上画一画就可以体会到)。

    对于第9行的 u := Extract_Min(Q) ,我们就用一个队列来表示Q,因为先进来的点的距离不会大于后进来的点,每次从队列头部取出元素,效果与Extract_Min(Q)一样。

    代码如下:

    POJ 3984
     1 #include <stdio.h>
     2 #include <string.h>
     3 
     4 #define N 5
     5 
     6 void print(int value, int prev[N*N])
     7 {
     8     if (value >= 0)
     9     {
    10         int x = value/N;
    11         int y = value%N;
    12         print(prev[value], prev);
    13         printf("(%d, %d)\n", x, y);
    14     }
    15 }
    16 
    17 void solve(int maze[N][N])
    18 {
    19     int visited[N][N];//是否被访问了
    20     memset(visited, 0, sizeof(visited));//初始化为0
    21 
    22     int offset[N-1][2] = {
    23         {1, 0},//向上
    24         {-1, 0},//向下
    25         {0, -1},//向左
    26         {0, 1}//向右
    27     };
    28 
    29     int queue[N*N];//队列
    30     int front = 0;//头指针
    31     int rear = 0;//尾指针
    32 
    33     int x = 0;//起点x坐标
    34     int y = 0;//起点y坐标
    35     queue[++rear] = 0;//向队列添加第一个点,即起始点
    36     visited[x][y] = 1;//0结点被访问过
    37 
    38     int prev[N*N];//保留每个点的前结点
    39     memset(prev, -1, sizeof(prev));//初始化为-1
    40     prev[0] = -1;//0的前结点为-1
    41 
    42     while (front <= rear)
    43     {
    44         int i;
    45         int newx;
    46         int newy;
    47         front++;//相当于弹出了一个结点
    48         x = queue[front]/N;
    49         y = queue[front]%N;
    50 
    51         for (i = 0; i < N - 1; i++)
    52         {
    53             newx = x + offset[i][0];//偏移之后的x坐标
    54             newy = y + offset[i][1];//偏移之后的y坐标
    55             if (newx >= 0 && newx < N && newy >= 0 && newy < N && !visited[newx][newy] && !maze[newx][newy])
    56             {
    57                 rear = (rear + 1)%(N*N);
    58                 queue[rear] = newx*N + newy;
    59                 prev[newx*N + newy] = x*N + y;
    60                 visited[newx][newy] = 1;
    61             }
    62         }
    63     }
    64     print(N*N - 1, prev);
    65 }
    66 
    67 int main()
    68 {
    69     int maze[N][N];
    70     int i = 0;
    71     int j = 0;
    72     while (scanf("%d", &maze[i][j++]) != EOF)
    73     {
    74         if (j == 5)
    75         {
    76             i++;
    77             j = 0;
    78         }
    79         if (i == 5)
    80         {
    81             solve(maze);
    82             i = 0;
    83         }
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    c语言 12
    c语言中用结构体表示点的坐标,并计算两点之间的距离
    c语言 12
    c语言中结构体数组
    c语言 12-3
    c语言 12-2
    codevs3164 质因数分解
    codevs4438 YJQ Runs Upstairs
    codevs4439 YJQ Requires Food
    codevs4437 YJQ Arranges Sequences
  • 原文地址:https://www.cnblogs.com/null00/p/2557907.html
Copyright © 2020-2023  润新知