zoukankan      html  css  js  c++  java
  • 《算法八》(广度寻路算法)

    广度寻路算法思路:
      遍历整个地图中所有可以走的点
      并且将其存入到一颗四叉树里
      之后从起点开始搜索这棵树查找终点即可

    1.各种类型定义:

    //点类型 
    struct MyPoint{
    	int row;
    	int col;
    };
    
    //方向枚举 
    enum direct{p_up,p_down,p_left,p_right};
    
    //辅助地图结点类型
    struct pathNode{
    	int		val;	
    	bool	isFind;
    };
    
    //树节点类型
    struct treeNode{
    	MyPoint				pos;
    	vector<treeNode*>	child;	//孩子    数组
    	treeNode*			pParent;//父
    };
    
    //创建一个树节点并返回节点首地址
    treeNode* CreateNode(int row, int col);
    //创建一个树节点并返回节点首地址
    treeNode* CreateNode(int row, int col){
    	treeNode* pNew = new treeNode;
    	memset(pNew, 0, sizeof(treeNode));
    	pNew->pos.row = row;
    	pNew->pos.col = col;
    	return pNew;
    }
    
    //判断pos点能不能走,能走返回true,不能返回false
    bool canWalk(pathNode pathMap[ROWS][COLS], MyPoint pos);
    //判断pos点能不能走,能走返回true,不能返回false
    bool canWalk(pathNode pathMap[ROWS][COLS], MyPoint pos){
    	if (pathMap[pos.row][pos.col].isFind)	//走过 
    		return false;
    	if (pathMap[pos.row][pos.col].val)		//障碍 
    		return false;
    	return true;
    }
    

    2.主要寻路代码:

    int main(){
    	//1 地图
    	int map[ROWS][COLS] = {
    		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    		{ 1, 0, 0, 0, 1, 0, 1, 1, 1, 1 },
    		{ 1, 0, 1, 0, 1, 0, 0, 0, 0, 1 },
    		{ 1, 0, 0, 0, 1, 0, 1, 1, 0, 1 },
    		{ 1, 0, 1, 0, 1, 0, 0, 0, 0, 1 },
    		{ 1, 0, 1, 0, 1, 0, 1, 1, 0, 1 },
    		{ 1, 0, 1, 0, 0, 0, 1, 1, 0, 1 },
    		{ 1, 0, 1, 0, 1, 0, 1, 1, 0, 1 },
    		{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
    	};
    
    	//2 辅助地图
    	pathNode pathMap[ROWS][COLS] = { 0 };
    	for (int i = 0; i < ROWS; i++){
    		for (int j = 0; j < COLS; j++)
    			pathMap[i][j].val = map[i][j];
    	}
    
    	//3 起点,终点
    	MyPoint begPos = { 1, 1 };
    	MyPoint endPos = { 8, 8 };
    
    	//4 准备树
    	treeNode* pRoot = NULL;
    
    	//5 起点为树的根节点
    	pRoot = CreateNode(begPos.row, begPos.col);
    	//6 标记起点已经走过
    	pathMap[begPos.row][begPos.col].isFind = true;
    	//7 寻路
    
    	//当前节点
    	MyPoint tempPos;
    	//当前层
    	vector<treeNode*> buff;
    	buff.push_back(pRoot);//树根为当前层
    	//临时树节点指针
    	treeNode* tempNode = NULL;
    
    	bool isFindEnd = false;//判断有没有找到终点 
    	while (1){
    #if 1
    		cout << "当前层:" << endl;
    		for (int i = 0; i < buff.size(); i++){
    			cout << "size:" << buff.size();
    			cout << "(" << buff[i]->pos.row << "," << buff[i]->pos.col << ") ";
    		}
    #endif
    		//下一层
    		vector<treeNode*> nextBuff;
    		for (int i = 0; i < buff.size(); i++){//当前层每一个结点找孩子
    			
    			for (int j = 0; j < 4; j++){//每一个结点都有四个方向
    			
    				tempPos = buff[i]->pos;//当前层每一个结点
    				switch (j){
    				case p_up:		tempPos.row--;	break;//上 y-- 
    				case p_down:	tempPos.row++;	break;//下 y++
    				case p_left:	tempPos.col--;	break;//左 x--
    				case p_right:	tempPos.col++;	break;//右 x++
    				}
    				
    				if (canWalk(pathMap,tempPos)){//如果能走
    					cout << "新节点:(" << tempPos.row << "," << tempPos.col << ")" << endl;
    					//标记新结点已经走过
    					pathMap[tempPos.row][tempPos.col].isFind = true;
    					
    					//创建树节点
    					tempNode = CreateNode(tempPos.row, tempPos.col);
    					//新节点入树
    					buff[i]->child.push_back(tempNode);	//当前点的孩子指针指向新结点
    					tempNode->pParent = buff[i];		//新节点的父指针指向当前点		
    
    					//新节点保存到下一层数组中
    					nextBuff.push_back(tempNode);
    					//新结点是否是终点,是终点,跳出循环
    					if (tempPos.row == endPos.row &&
    						tempPos.col == endPos.col){
    						isFindEnd = true;
    					}
    					if (isFindEnd) break;
    				}
    			}
    			if (isFindEnd) break;
    		}
    		if (isFindEnd) break;
    		if (nextBuff.size() == 0)//找到最后也没有找到 
    			break;
    			
    		buff = nextBuff;//继续向下一层找 
    	}
    	
    	if (isFindEnd){
    		cout << "路径:" << endl;
    		while (tempNode){
    			cout << "(" << tempNode->pos.row << "," << tempNode->pos.col << ")" << endl;
    			tempNode = tempNode->pParent;
    		}
    	}
    
    
    	while (1);
    	return 0;
    }
    

    3.全部完整代码:

    #include <iostream>
    #include <vector>
    #include<string.h> 
    using namespace std;
    
    #define ROWS  10
    #define COLS  10
    
    
    //点类型 
    struct MyPoint{
    	int row;
    	int col;
    };
    
    //方向枚举 
    enum direct{p_up,p_down,p_left,p_right};
    
    //辅助地图结点类型
    struct pathNode{
    	int		val;	
    	bool	isFind;
    };
    
    //树节点类型
    struct treeNode{
    	MyPoint				pos;
    	vector<treeNode*>	child;	//孩子    数组
    	treeNode*			pParent;//父
    };
    
    //创建一个树节点并返回节点首地址
    treeNode* CreateNode(int row, int col);
    //创建一个树节点并返回节点首地址
    treeNode* CreateNode(int row, int col){
    	treeNode* pNew = new treeNode;
    	memset(pNew, 0, sizeof(treeNode));
    	pNew->pos.row = row;
    	pNew->pos.col = col;
    	return pNew;
    }
    
    //判断pos点能不能走,能走返回true,不能返回false
    bool canWalk(pathNode pathMap[ROWS][COLS], MyPoint pos);
    //判断pos点能不能走,能走返回true,不能返回false
    bool canWalk(pathNode pathMap[ROWS][COLS], MyPoint pos){
    	if (pathMap[pos.row][pos.col].isFind)	//已经走过 
    		return false;
    	if (pathMap[pos.row][pos.col].val)		//有障碍物 
    		return false;
    	return true;
    }
    
    int main(){
    	//1 地图
    	int map[ROWS][COLS] = {
    		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    		{ 1, 0, 0, 0, 1, 0, 1, 1, 1, 1 },
    		{ 1, 0, 1, 0, 1, 0, 0, 0, 0, 1 },
    		{ 1, 0, 0, 0, 1, 0, 1, 1, 0, 1 },
    		{ 1, 0, 1, 0, 1, 0, 0, 0, 0, 1 },
    		{ 1, 0, 1, 0, 1, 0, 1, 1, 0, 1 },
    		{ 1, 0, 1, 0, 0, 0, 1, 1, 0, 1 },
    		{ 1, 0, 1, 0, 1, 0, 1, 1, 0, 1 },
    		{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
    	};
    
    	//2 辅助地图
    	pathNode pathMap[ROWS][COLS] = { 0 };
    	for (int i = 0; i < ROWS; i++){
    		for (int j = 0; j < COLS; j++)
    			pathMap[i][j].val = map[i][j];
    	}
    
    	//3 起点,终点
    	MyPoint begPos = { 1, 1 };
    	MyPoint endPos = { 8, 8 };
    
    	//4 准备树
    	treeNode* pRoot = NULL;
    
    	//5 起点为树的根节点
    	pRoot = CreateNode(begPos.row, begPos.col);
    	//6 标记起点已经走过
    	pathMap[begPos.row][begPos.col].isFind = true;
    	//7 寻路
    
    	//当前节点
    	MyPoint tempPos;
    	//当前层
    	vector<treeNode*> buff;
    	buff.push_back(pRoot);//树根为当前层
    	//临时树节点指针
    	treeNode* tempNode = NULL;
    
    	bool isFindEnd = false;//判断有没有找到终点 
    	while (1){
    #if 1
    		cout << "当前层:" << endl;
    		for (int i = 0; i < buff.size(); i++){
    			cout << "size:" << buff.size();
    			cout << "(" << buff[i]->pos.row << "," << buff[i]->pos.col << ") ";
    		}
    #endif
    		//下一层
    		vector<treeNode*> nextBuff;
    		for (int i = 0; i < buff.size(); i++){//当前层每一个结点找孩子
    			
    			for (int j = 0; j < 4; j++){//每一个结点都有四个方向
    			
    				tempPos = buff[i]->pos;//当前层每一个结点
    				switch (j){
    				case p_up:		tempPos.row--;	break;//上 y-- 
    				case p_down:	tempPos.row++;	break;//下 y++
    				case p_left:	tempPos.col--;	break;//左 x--
    				case p_right:	tempPos.col++;	break;//右 x++
    				}
    				
    				if (canWalk(pathMap,tempPos)){//如果能走
    					cout << "新节点:(" << tempPos.row << "," << tempPos.col << ")" << endl;
    					//标记新结点已经走过
    					pathMap[tempPos.row][tempPos.col].isFind = true;
    					
    					//创建树节点
    					tempNode = CreateNode(tempPos.row, tempPos.col);
    					//新节点入树
    					buff[i]->child.push_back(tempNode);	//当前点的孩子指针指向新结点
    					tempNode->pParent = buff[i];		//新节点的父指针指向当前点		
    
    					//新节点保存到下一层数组中
    					nextBuff.push_back(tempNode);
    					//新结点是否是终点,是终点,跳出循环
    					if (tempPos.row == endPos.row &&
    						tempPos.col == endPos.col){
    						isFindEnd = true;
    					}
    					if (isFindEnd) break;
    				}
    			}
    			if (isFindEnd) break;
    		}
    		if (isFindEnd) break;
    		if (nextBuff.size() == 0)//找到最后也没有找到 
    			break;
    			
    		buff = nextBuff;//继续向下一层找 
    	}
    	
    	if (isFindEnd){
    		cout << "路径:" << endl;
    		while (tempNode){
    			cout << "(" << tempNode->pos.row << "," << tempNode->pos.col << ")" << endl;
    			tempNode = tempNode->pParent;
    		}
    	}
    
    
    	while (1);
    	return 0;
    }
    
    //创建一个树节点并返回节点首地址
    treeNode* CreateNode(int row, int col){
    	treeNode* pNew = new treeNode;
    	memset(pNew, 0, sizeof(treeNode));
    	pNew->pos.row = row;
    	pNew->pos.col = col;
    	return pNew;
    }
    
    //判断pos点能不能走,能走返回true,不能返回false
    bool canWalk(pathNode pathMap[ROWS][COLS], MyPoint pos){
    	if (pathMap[pos.row][pos.col].isFind)	//走过 
    		return false;
    	if (pathMap[pos.row][pos.col].val)		//障碍 
    		return false;
    	return true;
    }
    
    
    
    /*
    	深度寻路:
    	有回退	循环少   适用于宽阔大地图   不一定能找到最短路径
    	广度寻路:
    	没有回退	循环多   适用与小地图       一定能找到最短路径
    	
    	都只能走直线
    */
    

    4.小总结:

      深度寻路:
        有回退 循环少 适用于宽阔大地图 不一定能找到最短路径
      广度寻路:
        没有回退 循环多 适用与小地图 一定能找到最短路径
      但是都只能走直线

  • 相关阅读:
    MySQL聚集索引和非聚集索引
    如何避免表单重复提交
    i++为什么是线程不安全的
    TIME_WAIT和CLOSE_WAIT
    TCP三次握手四次挥手
    get和post区别
    Session存储
    Session和Cookie的区别和联系
    Servlet与线程安全
    AQS
  • 原文地址:https://www.cnblogs.com/Whgy/p/12294394.html
Copyright © 2011-2022 走看看