【广度优先遍历】营救公主
题目描述:
公主被魔王抓走了,王子需要拯救出美丽的公主。他进入了魔王的城堡,魔王的城堡是一座很大的迷宫。为了使问题简单化,我们假设这个迷宫是一个N*M的二维方格。迷宫里有一些墙,王子不能通过。王子只能移动到相邻(上下左右四个方向)的方格内,并且一秒只能移动一步,就是说,如果王子在(x,y)一步只能移动到(x-1,y),(x+1,y),(x,y-1),(x,y+1)其中的一个位置上。地图由‘S’,‘P’,‘.’,‘*’四种符号构成,‘.’表示王子可以通过,‘*’表示墙,王子不能通过;'S'表示王子的位置;‘P’表示公主的位置;T表示公主存活的剩余时间,王子必须在T秒内到达公主的位置,才能救活公主。如下图所示:
上面是一个5*5的迷宫,红色箭头标识的是从S到P的一条路径。这条路径是最短的一条。如果题目中给的T是5的话,那么就无法救出公主。
解法:
对于这个迷宫问题,广度优先遍历可以找到一条最短的路径。我们把S作为树的根节点,其上下左右的点为孩子节点,那么首先肯定是看看孩子节点里面是不是公主。如果都不是的话,那么就查看某个孩子节点的4个孩子节点是否是公主。这也就是广度优先遍历了。首先我们给每个格子编个号码。然后我们把它变成树看看:
图没画完....... 发现我举的例子有些问题,数据太大了。
大致的树如上图所示,广度优先遍历,找到公主时看一下那时是第几层就就知道最短路径是几步了。那么,怎么维护这个层数呢?初始化时根的层数为0。遍历时,取出当前节点的层数,然后把所有孩子的层数设置为level+1,然后让所有孩子入队列。这样就可以知道找到公主时是第几层了。
代码如下:
#ifndef SAVE_PRINCESS_H
#define SAVE_PRINCESS_H/** 公主被魔王抓走了,王子需要拯救出美丽的公主。他进入了魔王的城堡,魔王的城堡是一座很大的迷宫。* 为了使问题简单化,我们假设这个迷宫是一个N*M的二维方格。迷宫里有一些墙,王子不能通过。王子只* 能移动到相邻(上下左右四个方向)的方格内,并且一秒只能移动一步,就是说,如果王子在(x,y)一步* 只能移动到(x-1,y),(x+1,y),(x,y-1),(x,y+1)其中的一个位置上。地图由‘S’,‘P’,‘.’,‘*’* 四种符号构成,‘.’表示王子可以通过,‘*’表示墙,王子不能通过;'S'表示王子的位置;‘P’表示公主* 的位置;T表示公主存活的剩余时间,王子必须在T秒内到达公主的位置,才能救活公主。如下图所示:*//* M行N列迷宫 * 如果能够救则返回1, 否则返回0*/
extern int save_princess(int M, int N, char* maze_data, int time);#endif
#include "save_princess.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>enum DIRECTION
{D_UP = 0,D_DOWN,D_LEFT,D_RIGHT,D_SIZE
};enum ROOM_TYPE
{TYPE_ROAD,TYPE_WINDOW,TYPE_PRINCE,TYPE_PRINCESS,
};struct room_info
{int row;int col;enum ROOM_TYPE type;int pass_by;struct room_info* child[D_SIZE];
};static void init_room(struct room_info* r)
{memset(r, 0, sizeof(*r));
}/* * 返回指向孩子的指针,孩子为墙则返回NULL* M*N 的迷宫,max_row = M - 1, max_col = N - 1*/
static struct room_info* get_child(struct room_info* maze, int max_row, int max_col, struct room_info* cur_room, enum DIRECTION direct)
{int row = 0;int col = 0;int idx = 0;struct room_info* child = NULL;if (NULL == maze|| NULL == cur_room){return NULL;}row = cur_room->row;col = cur_room->col;switch (direct){case D_UP:if (row <= 0){return NULL;}row--;break;case D_DOWN:if (row >= max_row){return NULL;}row++;break;case D_LEFT:if (col <= 0){return NULL;}col--;break;case D_RIGHT:if (col >= max_col){return NULL;}col++;break;default:break;}idx = row * (max_col + 1) + col;child = maze + idx;if (TYPE_WINDOW == child->type){return NULL;}else{return child;}
}/* 成功返回指向S的指针, 失败返回NULL*/
static struct room_info* init_maze(struct room_info* maze, int M, int N, char* maze_data)
{int row = 0;int col = 0;struct room_info* prince = NULL;/* 第一遍识别墙等,确定坐标 */for (row = 0; row < M; row++){for (col = 0; col < N; col++){int idx = row * N + col;char c = *(maze_data + idx);init_room(maze + idx);maze[idx].row = row;maze[idx].col = col;switch (c){case '.':maze[idx].type = TYPE_ROAD;break;case '*':maze[idx].type = TYPE_WINDOW;break;case 'S':prince = maze + idx;maze[idx].type = TYPE_PRINCE;break;case 'P':maze[idx].type = TYPE_PRINCESS;break;default:return NULL;}}}/*第二遍建立图*/for (row = 0; row < M; row++){for (col = 0; col < N; col++){int idx = row * N + col;maze[idx].child[D_UP] = get_child(maze, M - 1, N - 1, maze + idx, D_UP);maze[idx].child[D_DOWN] = get_child(maze, M - 1, N - 1, maze + idx, D_DOWN);maze[idx].child[D_LEFT] = get_child(maze, M - 1, N - 1, maze + idx, D_LEFT);maze[idx].child[D_RIGHT]= get_child(maze, M - 1, N - 1, maze + idx, D_RIGHT);}}return prince;
}struct node_info
{int level;struct room_info* room;struct node_info* parent;struct node_info* next;
};static void init_node_info(struct node_info* info)
{memset(info, 0, sizeof(*info));
}static void queue_push(struct node_info* queue, struct room_info* room, int cur_level, struct node_info* parent)
{struct node_info* new_node = NULL;if (NULL == room){return;}new_node = (struct node_info*)malloc(sizeof(struct node_info));init_node_info(new_node);new_node->level = cur_level + 1;new_node->parent = parent;new_node->room = room;while (queue != NULL){if (NULL == queue->next){queue->next = new_node;break;}queue = queue->next;}
}static void queue_release(struct node_info* queue)
{struct node_info* tmp = NULL;while (queue != NULL){tmp = queue->next;free(queue);queue = tmp;}
}/* 找到princess返回需要的步数* 找不到或者出错返回-1*/
static int find_princess(struct room_info* maze, struct room_info* prince)
{struct node_info* queue = NULL;struct node_info* cur_step = NULL;queue = (struct node_info*)malloc(sizeof(struct node_info));if (NULL == queue){return -1;}init_node_info(queue);queue->parent = NULL;queue->level = 0;queue->room = prince;cur_step = queue;while (cur_step != NULL){struct room_info* cur_room = cur_step->room;if (NULL == cur_room){fprintf(stderr, "IT CAN NOT HAPPEN!\n");break;}if (TYPE_PRINCESS == cur_room->type){struct node_info* tmp = cur_step;/* we find princess :) */fprintf(stdout, "\nThe way back to prince... \n");while (tmp != NULL){fprintf(stdout, "(%d, %d) ", tmp->room->row, tmp->room->col);tmp = tmp->parent;}fprintf(stdout, "\n");queue_release(queue);return cur_step->level;}else if (TYPE_ROAD == cur_room->type|| TYPE_PRINCE == cur_room->type){struct room_info* tmp = NULL;if (1 == cur_room->pass_by){cur_step = cur_step->next;continue;}cur_room->pass_by = 1;/* 把孩子们丢到队列后面 */tmp = cur_room->child[D_UP];queue_push(queue, tmp, cur_step->level, cur_step);tmp = cur_room->child[D_DOWN];queue_push(queue, tmp, cur_step->level, cur_step);tmp = cur_room->child[D_LEFT];queue_push(queue, tmp, cur_step->level, cur_step);tmp = cur_room->child[D_RIGHT];queue_push(queue, tmp, cur_step->level, cur_step);}else {fprintf(stderr, "Wired!\n");}cur_step = cur_step->next;}queue_release(queue);return -1;
}int save_princess(int M, int N, char* maze_data, int time)
{struct room_info* maze = NULL;struct room_info* prince = NULL;int time_need = 0;if (M <= 1|| N <= 1|| NULL == maze_data|| 0 == time){return 0;}maze = (struct room_info*)malloc(M * N * sizeof(struct room_info));if (NULL == maze){return 0;}prince = init_maze(maze, M, N, maze_data);if (NULL == prince){/*输入数据有误*/return 0;}time_need = find_princess(maze, prince);if (-1 == time_need){return 0;}else if (time_need > time){return 0;}else{return 1;}
}
#include "save_princess.h"
#include <stdio.h>#define M 10
#define N 10int main()
{int ret = 0;int row = 0;int col = 0;char maze_info[M][N] = {\/* 0 1 2 3 4 5 6 7 8 9*//*0*/ {'.', '.', '.', '*', '.', '.', '.', '.', '.', '.'},/*1*/ {'.', 'S', '*', '.', '.', '.', '.', '.', '.', '.'},/*2*/ {'.', '.', '*', '.', '.', '.', '.', '.', '.', '.'},/*3*/ {'.', '.', '*', '*', '.', '*', '.', '.', '.', '.'},/*4*/ {'.', '.', '.', '*', '.', '*', '.', '.', '.', '.'},/*5*/ {'.', '.', '.', '*', '.', '.', '.', '.', '.', '.'},/*6*/ {'.', '.', '*', '.', '.', '.', '.', '.', '.', '.'},/*7*/ {'.', '.', '*', '.', '*', '.', '*', '.', '.', '.'},/*8*/ {'.', '.', '.', '.', '*', '.', '*', '*', '*', '.'},/*9*/ {'.', '.', '*', '.', '*', '.', '*', 'P', '.', '.'}};fprintf(stdout, "\n ");for (col = 0; col < N; col++){fprintf(stdout, "%d ", col);}fprintf(stdout, "\n");for (row = 0; row < M; row++){fprintf(stdout, "%d ", row);for (col = 0; col < N; col++){fprintf(stdout, "%c ", maze_info[row][col]);}fprintf(stdout, "\n");}ret = save_princess(M, N, (char*)maze_info, 6);fprintf(stdout, "\n");system("pause");return 0;
}
测试结果:
【广度优先遍历】营救公主相关推荐
- java拯救公主_广度优先搜索解决“营救公主”问题
在之前的一篇文章(迷宫营救公主算法)中提供了一个半成品的解决方案,之所以说他是半成品,是因为首先选择的算法就不对,采用的是深度优先搜索,其次也没有真正的用对深度优先算法,走过的点应该标记为已经走过,而 ...
- [C] 图的广度优先遍历
图的广度优先遍历 我一直觉得图的遍历没有地图类型的题目难,遍历嘛,每个点都走一遍就行了. 但是给定地图求面积啊,数量啊的那种题目,花样挺多的. 图的遍历真挺难把人绕晕的,关于广度优先,理解好层层递进这 ...
- 数据结构与算法(7-2)图的遍历(深度优先遍历DFS、广度优先遍历BFS)(分别用邻接矩阵和邻接表实现)
目录 深度优先遍历(DFS)和广度优先遍历(BFS)原理 1.自己的原理图 2.官方原理图 一.邻接矩阵的深度优先遍历(DFS) 1.原理图 2. 过程: 3.总代码 二.邻接表的深度优先遍历(DFS ...
- python迷宫万花筒代码_利用广度优先遍历搜索迷宫的python源代码
广度优先遍历简称为DFS,是数据结构中比较常用的一个算法,主要原理是采用队列先进先出的规则,一层一层的访问图的节点.而迷宫问题接近与遍历,但是不同于遍历,主要考虑是采用栈的形式标记路径,并对当前节点和 ...
- 邻接表存储图的广度优先遍历
试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(Vertex) ); 其中LGraph是邻接表存储 ...
- 三十二、图的创建深度优先遍历(DFS)广度优先遍历(BFS)
一.图的基本介绍 为什么要有图 前面我们学了线性表和树 线性表局限于一个直接前驱和一个直接后继的关系 树也只能有一个直接前驱也就是父节点 当我们需要表示多对多的关系时, 这里我们就用到了图. 图的举例 ...
- python创建树结构、求深度_数据结构-树以及深度、广度优先遍历(递归和非递归,python实现)...
前面我们介绍了队列.堆栈.链表,你亲自动手实践了吗?今天我们来到了树的部分,树在数据结构中是非常重要的一部分,树的应用有很多很多,树的种类也有很多很多,今天我们就先来创建一个普通的树.其他各种各样的树 ...
- 数据结构 图的广度优先遍历 C++
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Bool ...
- 二叉树深度优先遍历和广度优先遍历
二叉树深度优先遍历和广度优先遍历
最新文章
- 重磅MIT开源人工智能算法评估和理解对抗Logit配对的稳健性
- restTemplate的介绍和使用
- 一天学完spark的Scala基础语法教程九、迭代器(idea版本)
- 看看老司机是如何提升B端产品架构能力的
- java webtable_java winform开发:JTable详解
- LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal
- 接下来会普及流行能实现《集中授权集中管理,分级授权逐级管理》的标准化权限系统...
- 听说3月15日深圳有场存储盛宴,约吗?
- oracle sql执行计划分析
- 小旋风万能蜘蛛池 小霸王蜘蛛池快速收录源码
- SLAM导航全栈书的正确打开方式(强烈推荐)
- Granger格兰杰因果关系的设计、基本假设和额外要求
- 贴片电阻的封装、功率
- 基于ESP8266的STM32物联网开发板
- 智能人员考勤系统(C语言)
- 苹果手机的专用充电宝有哪些?苹果官方授权无线充电宝推荐
- 深入探究JVM(1) - Java的内存区域解析
- Rocket MQ(四)Topic,Topic分片和Queue
- 传智博客学习笔记8--面向对象下
- 使用冰封重装系统遇到的问题及解决方案