1.算法说明
[1]广度优先搜索算法(BFS)主要用于计算源点到目标点的最短路径。
[2]BFS的基本实现是使用队列,从源点开始入队列,访问后把临近节点入队列,之后出队列,再访问刚加进的临近节点,以此反复访问,知道达到目标点。
2.算法步骤
1. 首先将根节点放入队列中。
2. 从队列中取出第一个节点,并检验它是否为目标,如果找到目标,则结束搜寻并回传结果,否则将它所有尚未检验过的直接子节点加入队列中。
3. 若队列为空,表示整张图都检查过了,此时可以返回结果,否则重复步骤2。
更具体地:
以白色表示未达到的节点,灰色表示边缘节点(意思是需要从这些节点继续搜索),黑色表示已经达到的节点。
1.在搜索的过程中,初始所有节点是白色,把起点V0标志成灰色。
2.访问所有灰色的节点的临近节点,如果临近节点是白色,则把这些临近节点变为灰色(此时判断染灰色的节点是否为目标节点,如果是则表示完成),否则表示已经到达过则不处理,并把当前节点变成黑色。
3.重复第2步。
3.例子
描述:
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),
找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
输入格式:
输入初试状态,一行九个数字,空格用0表示
输出格式:
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
代码:
#include<cstdio> #include<cstring> #include<map> #include<stdlib.h> using namespace std; const int M=400000; /* 每个0位置状态时,可以移动的位置 例如0在位置0时,可以移动到1和3位置。 */ int g_change_position[9][4]={{-1,-1,3,1},{-1,0,4,2},{-1,1,5,-1}, {0,-1,6,4},{1,3,7,5},{2,4,8,-1}, {3,-1,-1,7},{4,6,-1,8},{5,7,-1,-1} }; int g_target = 123804765; /* g_map用来记录状态是否达到过,如果未达到过,则加入que队列。 如果达到过则什么都不处理。 例如初始把起点加入队列,并且设置为该状态为1,表示已达到过。 */ map<int,bool> g_map; /* 9!是362880,表示012345678这九个数字共有362880种排列组合 [][0] :排列值 [][1] :空位0的位置 [][2] :到此排列状态所走的步数 que[400000]就是BFS的队列,把将要搜索的节点放入队列,之后再顺序访问队列。 */ int que[400000][3]; // 交换字符串中的两个位置 void swap(char *c,int a,int b){ char t=c[a]; c[a]=c[b]; c[b]=t; } /* head表示队列que的起点,tail表示队列que的终点,达到终点则退出。 初始时,把起点加入队列,此时队列长度为1,因此起点为0,终点为1。 队列中加入新节点时,队列终点后移。 当前状态搜索临近节点后,把临近节点加入队列,队列搜索位置后移。 */ int bfs(int n, int p) { int i, swap_pos; int head=0,tail=1,temp; //设置起点状态达到,并且加入队列 g_map[n]=1; que[head][0] = n; que[head][1] = p; que[head][2] = head; while(head != tail){ char cur[10]; int pos = que[head][1]; //当前状态0的位置 sprintf(cur, "%09d", que[head][0]); //要交换的四个位置,上下左右 for(i=0;i<4;i++){ swap_pos = g_change_position[pos][i]; if(swap_pos == -1) continue; //交换0的位置,得到新的状态,转为int,保存到temp swap(cur, pos, swap_pos); sscanf(cur,"%d",&temp); if(temp == g_target) return que[head][2] + 1; //如果 新的状态没有出现过,则将这个新状态加到map if(g_map.count(temp) == 0){ que[tail][0]=temp; que[tail][1]=swap_pos; que[tail][2]=que[head][2]+1; tail++; g_map[temp] = 1; } //一个新状态处理完了一定要记得将交换的0交换回来 swap(cur, pos, swap_pos); } head++; } } int main() { int n, i = -1, count = 0; char start[10]; printf("input start array: "); scanf("%s", start); n = atoi(start); while(start[++i] != '0'); //查找初始状态0的位置 if(n != g_target) count = bfs(n, i); printf("%d", count); return 0; }
[1]BFS搜索时,最基本是用了队列que来保存已到达的状态,之后顺序访问队列,把新状态再加到队列中。