题目描述:

公主被魔王抓走了,王子需要拯救出美丽的公主。他进入了魔王的城堡,魔王的城堡是一座很大的迷宫。为了使问题简单化,我们假设这个迷宫是一个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;
}

测试结果:

【广度优先遍历】营救公主相关推荐

  1. java拯救公主_广度优先搜索解决“营救公主”问题

    在之前的一篇文章(迷宫营救公主算法)中提供了一个半成品的解决方案,之所以说他是半成品,是因为首先选择的算法就不对,采用的是深度优先搜索,其次也没有真正的用对深度优先算法,走过的点应该标记为已经走过,而 ...

  2. [C] 图的广度优先遍历

    图的广度优先遍历 我一直觉得图的遍历没有地图类型的题目难,遍历嘛,每个点都走一遍就行了. 但是给定地图求面积啊,数量啊的那种题目,花样挺多的. 图的遍历真挺难把人绕晕的,关于广度优先,理解好层层递进这 ...

  3. 数据结构与算法(7-2)图的遍历(深度优先遍历DFS、广度优先遍历BFS)(分别用邻接矩阵和邻接表实现)

    目录 深度优先遍历(DFS)和广度优先遍历(BFS)原理 1.自己的原理图 2.官方原理图 一.邻接矩阵的深度优先遍历(DFS) 1.原理图 2. 过程: 3.总代码 二.邻接表的深度优先遍历(DFS ...

  4. python迷宫万花筒代码_利用广度优先遍历搜索迷宫的python源代码

    广度优先遍历简称为DFS,是数据结构中比较常用的一个算法,主要原理是采用队列先进先出的规则,一层一层的访问图的节点.而迷宫问题接近与遍历,但是不同于遍历,主要考虑是采用栈的形式标记路径,并对当前节点和 ...

  5. 邻接表存储图的广度优先遍历

    试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(Vertex) ); 其中LGraph是邻接表存储 ...

  6. 三十二、图的创建深度优先遍历(DFS)广度优先遍历(BFS)

    一.图的基本介绍 为什么要有图 前面我们学了线性表和树 线性表局限于一个直接前驱和一个直接后继的关系 树也只能有一个直接前驱也就是父节点 当我们需要表示多对多的关系时, 这里我们就用到了图. 图的举例 ...

  7. python创建树结构、求深度_数据结构-树以及深度、广度优先遍历(递归和非递归,python实现)...

    前面我们介绍了队列.堆栈.链表,你亲自动手实践了吗?今天我们来到了树的部分,树在数据结构中是非常重要的一部分,树的应用有很多很多,树的种类也有很多很多,今天我们就先来创建一个普通的树.其他各种各样的树 ...

  8. 数据结构 图的广度优先遍历 C++

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Bool ...

  9. 二叉树深度优先遍历和广度优先遍历

    二叉树深度优先遍历和广度优先遍历

最新文章

  1. 重磅MIT开源人工智能算法评估和理解对抗Logit配对的稳健性
  2. restTemplate的介绍和使用
  3. 一天学完spark的Scala基础语法教程九、迭代器(idea版本)
  4. 看看老司机是如何提升B端产品架构能力的
  5. java webtable_java winform开发:JTable详解
  6. LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal
  7. 接下来会普及流行能实现《集中授权集中管理,分级授权逐级管理》的标准化权限系统...
  8. 听说3月15日深圳有场存储盛宴,约吗?
  9. oracle sql执行计划分析
  10. 小旋风万能蜘蛛池 小霸王蜘蛛池快速收录源码
  11. SLAM导航全栈书的正确打开方式(强烈推荐)
  12. Granger格兰杰因果关系的设计、基本假设和额外要求
  13. 贴片电阻的封装、功率
  14. 基于ESP8266的STM32物联网开发板
  15. 智能人员考勤系统(C语言)
  16. 苹果手机的专用充电宝有哪些?苹果官方授权无线充电宝推荐
  17. 深入探究JVM(1) - Java的内存区域解析
  18. Rocket MQ(四)Topic,Topic分片和Queue
  19. 传智博客学习笔记8--面向对象下
  20. 使用冰封重装系统遇到的问题及解决方案

热门文章

  1. [i春秋]“百度杯”CTF比赛 十月场-Hash
  2. C语言—循环结构 打印输出如下图所示的下三角形乘法九九表
  3. Hitchhiker加解密脚本
  4. 交作业:pygame中的库
  5. 【大模型】大语言模型简介
  6. Java中的23个设计模式 【结构型模式】 中的 【享元模式】
  7. 社群积分怎么玩?社群积分系统用哪个?
  8. ConstraintLayout布局内容被手机底部导航条遮住问题
  9. fckeditor在.net中的使用
  10. Winfrom下的socket TCP基础通信