回溯法之迷宫问题

参考:http://www.cnblogs.com/hustcat/archive/2008/04/09/1144645.html

方法:(回溯法)

1、总结问题解决问题的思想。

2、总结具体的算法流程和典型问题解决思路。

3、编程实现具体实例。

将这个方法推广到其他算法上,快速高效的掌握算法思想。

回溯法一种系统的搜索问题解答的办法。

1、思想:碰壁返回

2、算法流程:首先定义一个解空间,这个解空间必须至少包含问题的一个解。其次需要组织解空间使它容易被搜索,典型的组织方法是图或者二叉搜索树。最后按深度优先搜索的方法从开始结点开始搜索。

在搜索的任意时刻,只保存开始结点到当前结点的路径。

3、具体实例(迷宫问题)

// Maze.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<stack>
#include<iostream>
using namespace std;

#define MazeNum 10



//通道块坐标结点
struct PosType
{
	int x;		//横坐标
	int y;		//纵坐标
};
//入栈结点类型
struct SElemType
{
	int ord;	//通道块在路径上的序号
	PosType seat;	//通道块在迷宫中的坐标位置
	int di;		//从此通道块走向下一个通道的方向
};

//路径全局变量
PosType path[64];

int _tmain(int argc, _TCHAR* argv[])
{
	cout<<"----------------回溯法求解迷宫问题----------"<<endl;
	int maze[MazeNum][MazeNum]=		//迷宫方阵 入口:(1,1) 出口:(8,8)
	{
		{1,1,1,1,1,1,1,1,1,1},//0
		{1,0,0,1,0,0,0,1,0,1},//1
		{1,0,0,1,0,0,0,1,0,1},//2
		{1,0,0,0,0,1,1,0,0,1},//3
		{1,0,1,1,1,0,0,0,0,1},//4
		{1,0,0,0,1,0,0,0,0,1},//5
		{1,0,1,0,0,0,1,0,0,1},//6
		{1,0,1,1,1,0,1,1,0,1},//7
		{1,1,0,0,0,0,0,0,0,1},//8
		{1,1,1,1,1,1,1,1,1,1} //9
	};
	//初始化路径数组
	for(int i=0;i<64;i++)
	{
		path[i].x=0;
		path[i].y=0;
	}

	PosType start,end;
	start.x=1;
	start.y=1;
	end.x=8;
	end.y=8;
	PosType NextPosition(PosType curpos,int di);
	bool Maze(int maze[MazeNum][MazeNum],PosType start,PosType end);
	void PrintPath();
	
	//如果该迷宫可以通行,则打印路径
	if(Maze(maze,start,end))
	{
		PrintPath();
	}
	else
	{
		cout<<"从起点到终点木有路径可达"<<endl;
	}

	return 0;
}//main

//选择当前位置的下一个位置:1:东 2:南 3:西 4:北
PosType NextPosition(PosType curpos,int di)
{
	PosType nextpos;
	switch (di)
	{
	case 1:		//东
		nextpos.x=curpos.x+1;
		nextpos.y=curpos.y;
		return nextpos;
		break;
	case 2:		//南
		nextpos.x=curpos.x;
		nextpos.y=curpos.y+1;
		return nextpos;
		break;
	case 3:		//西
		nextpos.x=curpos.x-1;
		nextpos.y=curpos.y;
		return nextpos;
		break;
	case 4:		//北
		nextpos.x=curpos.x;
		nextpos.y=curpos.y-1;
		return nextpos;
	default:
		break;
	}
}//NextPosition




//迷宫算法
bool Maze(int maze[MazeNum][MazeNum],PosType start,PosType end)
{
	PosType cur_postion=start;	//设定当前位置为入口位置
	int curstep=0;				//探索第一步
	stack<SElemType> m_stack;	//初始化栈
	SElemType setType;
	do
	{
		//如果当前位置可以通过
		if (maze[cur_postion.x][cur_postion.y]==0)
		{
			setType.ord=curstep;
			setType.seat=cur_postion;
			setType.di=1;
			
			//记录该路径
			path[curstep]=cur_postion;

			m_stack.push(setType);	//入栈

			//如果当前位置等于终点,则结束,否则切换到当前位置的东邻方向
			if(cur_postion.x==end.x && cur_postion.y==end.y)return true;
			
			cur_postion=NextPosition(cur_postion,1);	//切换到下一个位置
			curstep++;		//当前路径长度加1
			
		}
		//如果当前位置不能通过,则回溯
		else
		{
			//当前栈不为空,且有其他方向没有探索
			if(!m_stack.empty())
			{
				
				setType=m_stack.top();		//访问栈顶元素
				cur_postion=setType.seat;	//返回上一个位置
				m_stack.pop();				//删除栈顶元素

				while(setType.di==4 && !m_stack.empty())
				{
				//	m_stack.pop();	//如果某个路径的其他路径都不通,只能后退一步
				}//while
				if(setType.di<4)			//还有其他方向未被探索
				{
					setType.di++;			//切换到下一个方向
					cur_postion	=NextPosition(cur_postion,setType.di);
						
				}

			}

		}

	} while (!m_stack.empty());
	return false;
}//Maze

//打印路径
void PrintPath()
{
	int i=0;
	while(path[i].x!=0 && path[i].y!=0)
	{
		cout<<"("<<path[i].x<<","<<path[i].y<<")"<<"-->";
		i++;
		if(i%4==0)
			cout<<endl;
	}
	cout<<endl;
}//PrintPath

声明:此程序中存在一点小bug,待修复。

 

posted @ 2013-06-04 14:55  李VS超  阅读(570)  评论(0编辑  收藏  举报