宽度优先搜索

宽度优先搜索(又称广度优先搜索,简称BFS),一种先生成的节点,先扩展的策略。 搜索过程:从初始节点开始逐层向下扩展,在第n层节点还没搜索结束之前,不能进入第n+1层搜索(需要使用队列实现) (1) 把初始节点放入到队列中 (2) 如果队列为空,则问题无解,跳出循环 (3) 取出队列中的第一个元素,并记该节点为cur,并将队列第一个元素删除 (4) 考察cur节点是否为目标节点,如果是目标节点则问题解决,跳出循环 (5) 若节点cur不能扩展则跳到第二步; (6) 若节点cur可以扩展,将其子节点放入队列的尾部,跳到第二步 例题:走迷宫问题 给定一个二维数组 int map[5][5] = { 0 , 1 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 0 , } ; 它表示一个迷宫,其中“1”表示墙壁,“0”表示可以走的路,只能横着走或者竖着走,不能斜着走,要求编写程序求出从左上角到右下角的最短路径的长度,例如上述问题输出结果为:8
#include
#include
#include
#include
#include
using namespace std ;
int a[100][100] , vis[100][100] = {0} ;
int m , n ;
struct dot{
    int x ;
    int y ;
    int step ;
};
int dx[] = {-1,0,1,0} ;
int dy[] = {0,1,0,-1} ;
bool is_ok(dot cur) {
    if(cur.x < 0|| cur.x >= m || cur.y < 0 || cur.y >= n )
        return 0 ;
    return 1 ;
}
int bfs()   {
    dot A ;
    A.x = 0 ;
    A.y = 0 ;
    A.step = 0 ;
    vis[0][0] = 1 ;
    queue  q ;
    while(!q.empty())
        q.pop() ;
    q.push(A) ;
    while(!q.empty())   {
        dot cur = q.front() ;
        q.pop();
        if(cur.x == m-1 && cur.y == n-1)
            return cur.step ;
        dot next ;
        for(int i = 0 ; i < 4 ; i++)    {
            next.x = cur.x + dx[i] ;
            next.y = cur.y + dy[i] ;
            next.step = cur.step + 1 ;
            if(is_ok(next)&&a[next.x][next.y] != 1&&vis[next.x][next.y] != 1)    {
                q.push(next) ;
                vis[next.x][next.y] = 1 ;
            }
        }
    }
    return 0 ;
}
int main()  {
    scanf("%d%d",&m,&n) ;
    int i , j , k ;
    for(i = 0 ; i < m ; i++)
        for(j = 0 ; j < n ; j++)
            scanf("%d",&a[i][j]) ;
    int step = bfs() ;
    printf("%d\n",step) ;
    return 0 ;
}
当节点足够多时,有可能会超出队列的容量,程序在运行时就会出错,所以也可以使用数组代替队列。
#include
#include
#include
#include
using namespace std ;
int a[100][100] , vis[100][100] = {0} ;
int m , n ;
struct dot{
    int x ;
    int y ;
    int step ;
}d[10000];
int dx[] = {-1,0,1,0} ;
int dy[] = {0,1,0,-1} ;
bool is_ok(dot cur) {
    if(cur.x < 0|| cur.x >= m || cur.y < 0 || cur.y >= n )
        return 0 ;
    return 1 ;
}
int bfs()   {
    dot A ;
    A.x = 0 ;
    A.y = 0 ;
    A.step = 0 ;
    vis[0][0] = 1 ;
    int head = 0 , tail = 0 ;
    d[tail++] = A ;
    while(head < tail)   {
        dot cur = d[head++] ;
        if(cur.x == m-1 && cur.y == n-1)
            return cur.step ;
        dot next ;
        for(int i = 0 ; i < 4 ; i++)    {
            next.x = cur.x + dx[i] ;
            next.y = cur.y + dy[i] ;
            next.step = cur.step + 1 ;
            if(is_ok(next)&&a[next.x][next.y] != 1&&vis[next.x][next.y] != 1)    {
                d[tail++] = next ; ;
                vis[next.x][next.y] = 1 ;
            }
        }
    }
    return 0 ;
}
int main()  {
    scanf("%d%d",&m,&n) ;
    int i , j , k ;
    for(i = 0 ; i < m ; i++)
        for(j = 0 ; j < n ; j++)
            scanf("%d",&a[i][j]) ;
    int step = bfs() ;
    printf("%d\n",step) ;
    return 0 ;
}
如果想输出所走的路径,可以先记录各个节点的父节点位置,然后递归输出路径:
#include
#include
#include
#include
using namespace std ;
int a[100][100] , vis[100][100] = {0} ;
int m , n ;
struct dot{
    int x ;
    int y ;
    int step ;
}d[10000];
int pre[10000] ;
int dx[] = {-1,0,1,0} ;
int dy[] = {0,1,0,-1} ;
bool is_ok(dot cur) {
    if(cur.x < 0|| cur.x >= m || cur.y < 0 || cur.y >= n )
        return 0 ;
    return 1 ;
}
void print(int x)    {  //递归输出
    int t = pre[x] ;
    if(t == 0)  {
        printf("(0,0)\n") ;  //先输出父节点位置
        printf("(%d,%d)\n" ,d[x].x , d[x].y) ;  //再输出本身位置
        return ;
    }
    print(t) ;   //先输出父节点位置
    printf("(%d,%d)\n" ,d[x].x , d[x].y) ;     //再输出本身位置
}
int bfs()   {
    dot A ;
    A.x = 0 ;
    A.y = 0 ;
    A.step = 0 ;
    vis[0][0] = 1 ;
    int head = 0 , tail = 0 ;
    d[tail++] = A ;
    while(head < tail)   {
        dot cur = d[head++] ;
        if(cur.x == m-1 && cur.y == n-1)    {
            print(head-1) ;
            return cur.step ;
        }
        dot next ;
        for(int i = 0 ; i < 4 ; i++)    {
            next.x = cur.x + dx[i] ;
            next.y = cur.y + dy[i] ;
            next.step = cur.step + 1 ;
            if(is_ok(next)&&a[next.x][next.y] != 1&&vis[next.x][next.y] != 1)    {
                pre[tail] = head - 1 ;  //记录该节点的父节点所在位置
                d[tail++] = next ; ;
                vis[next.x][next.y] = 1 ;
            }
        }
    }
    return 0 ;
}

int main()  {
    scanf("%d%d",&m,&n) ;
    int i , j , k ;
    for(i = 0 ; i < m ; i++)
        for(j = 0 ; j < n ; j++)
            scanf("%d",&a[i][j]) ;
    int step = bfs() ;
    printf("%d\n",step) ;
    return 0 ;
}
posted @ 2014-10-18 12:16  NYNU_ACM  阅读(435)  评论(0编辑  收藏  举报