双向BFS初步——c++代码分析

来源:互联网 发布:淘宝红人模特排行榜 编辑:程序博客网 时间:2024/04/28 09:37

我们从广为人知的POJ 2243这道题谈起:题目大意:给定一个起点和一个终点,按骑士的走法(走日字),从起点到终点的最少移动多少次



先看代码:加了注释,然后解释:


#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;struct knight{    int x,y,step;};int dir[8][2]={{-2,-1},{-2,1},{2,-1},{2,1},{-1,-2},{-1,2},{1,-2},{1,2}};int sx, sy, ex, ey;int visit[8][8];int color[8][8];int bfs();int main(){    int x1, x2;    char y1, y2;    while(scanf("%c%d %c%d", &y1, &x1, &y2, &x2) != EOF)    {        getchar();        sx = x1 - 1;        sy = y1 - 'a';        ex = x2 - 1;        ey = y2 - 'a';        memset(visit, -1, sizeof(visit));        memset(color, 0, sizeof(color));        int cost = bfs();        printf("To get from %c%d to %c%d takes %d knight moves.\n", y1, x1, y2, x2, cost);    }    return 0;}int bfs(){    if(sx == ex && sy == ey)        return 0;    queue<knight> que_front;//创建队列     queue<knight> que_back;    knight front, back;//结构体     front.x = sx; front.y = sy; front.step = 0;//赋初值     back.x = ex; back.y = ey; back.step = 1;    que_front.push(front);//进队列     que_back.push(back);//进队列     visit[sx][sy] = 0;    visit[ex][ey] = 1;    //由这两个来区分这两个队列 color[sx][sy] = 1;    color[ex][ey] = 2;    int ans1 = 0, ans2 = 0;    while(!que_front.empty() || !que_back.empty())//当两个队列都为空时退出     {        if(!que_front.empty())//队列不空         {            front = que_front.front();//结构体赋值             que_front.pop();//出队列             for(int i = 0; i < 8; i++)            {                int dx = front.x + dir[i][0];                int dy = front.y + dir[i][1];                if(dx >= 0 && dx < 8 && dy >= 0 && dy < 8 && color[dx][dy] != 1)//判断是否被队列1走过                 {                    if(color[dx][dy] == 0)                    {                        knight tmp;//建立新结构体,并赋值                         tmp.x = dx; tmp.y = dy;                        tmp.step = front.step + 1;                        visit[dx][dy] = tmp.step;//记录相应步数                         color[dx][dy] = 1;//赋队列1的标记值                         que_front.push(tmp);//进队列                     }                    else  //即不等于1也不等于0  则肯定是等于2,所以两个相交                         return front.step + visit[dx][dy];                }            }        }        if(!que_back.empty())//第二个和第一个同理         {            back = que_back.front();            que_back.pop();            for(int i = 0; i < 8; i++)            {                int dx = back.x + dir[i][0];                int dy = back.y + dir[i][1];                if(dx >= 0 && dx < 8 && dy >= 0 && dy < 8 && color[dx][dy] != 2)                {                    if(color[dx][dy] == 0)                    {                        knight tmp;                        tmp.x = dx; tmp.y = dy;                        tmp.step = back.step + 1;                        visit[dx][dy] = tmp.step;                        color[dx][dy] = 2;                        que_back.push(tmp);                    }                    else                        return back.step + visit[dx][dy];                }                            }        }    }    return -1;//没有路径相通,则返回-1 }


分析:其实其和BFS并没有多大差别,只是它用了两个队列,而其核心部分为1和2的标记,利用标记来判断其是否相交,所有color数组为其能够双向的核心部分,其次visit数组用来记录步数,也是其相连的关键!

综上:要格外注意visit[]和color[]这两个数组,,这是其核心!!!


0 0
原创粉丝点击