参考: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,待修复。