[poj3984]
来源:互联网 发布:java cookie 编辑:程序博客网 时间:2024/04/28 19:42
原文出处:http://www.cnblogs.com/shuaiwhu/archive/2012/06/22/2557907.html
迷宫问题
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)一样。
代码如下:
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));//初始化为021 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));//初始化为-140 prev[0] = -1;//0的前结点为-141 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 }
- poj3984
- poj3984
- POJ3984
- poj3984
- poj3984
- poj3984
- [poj3984]
- poj3984
- POJ3984
- poj3984
- poj3984
- POJ3984
- POJ3984
- poj3984--BFS
- POJ3984迷宫
- bfs poj3984
- POJ3984 迷宫问题 BFS
- POJ3984 迷宫问题
- 45.UIAlertController和常见传值
- 打印hostent结构体中的所有内容
- HTML访问CGI
- 软件版本号规范说明
- 陈焕生:深入理解Oracle 的并行执行
- [poj3984]
- Android修改init.rc和init.xx.rc文件
- java 自带的MD5、SHA1算法演示
- "abc" full arrange - III
- UVALive 6655 Two Points Revisited
- Objective-C 苹果开发文档 09 Dealing with Errors
- Qt入门学习——Qt快速入门(vim纯代码编写)
- 微信JS SDK Demo
- IOS学习之OC面向对象—多态