bfs 最短路径

题目要求

东东有一张地图,想通过地图找到妹纸。地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹纸,这两个位置保证为0。既然已经知道了地图,那么东东找到妹纸就不难了,请你编一个程序,写出东东找到妹纸的最短路线。
输入是一个5 × 5的二维数组,仅由0、1两数字组成,表示法阵地图。
输出若干行,表示从左上角到右下角的最短路径依次经过的坐标,格式如样例所示。数据保证有唯一解。
Sample Input

0 1 0 0 0
0 1 0 1 0
0 1 0 1 0
0 0 0 1 0
0 1 0 1 0

Sample Output

(0, 0)
(1, 0)
(2, 0)
(3, 0)
(3, 1)
(3, 2)
(2, 2)
(1, 2)
(0, 2)
(0, 3)
(0, 4)
(1, 4)
(2, 4)
(3, 4)
(4, 4)

思路

1、使用二维数组记录地图,二维数组的下标为地图的坐标。为区分未到达的位置0和障碍物1,将起点值记为2,途径点的值记为据起点的距离+2。
2、使用队列进行广度优先搜索。首先将起点压入队列,从队列中弹出一个点A后,访问该点的上下左右四个位置B,进行如下操作:

判断B点是否在地图范围之内,因为是直接将地图读入二维数组,访问边界点的四个方位可能会超出数组范围,可以替代的做法是将地图周围加入一圈障碍物.

判断B点是否未到达,若值为0,则将该点值记为 A点的值+1

终止条件为找到终点或队列为空,因为该题数据保证有唯一解,所以一定能找到终点,终点值-起点值 为最短路径长度

3、找到终点后,输出最短路径。一个很重要的问题是不能直接从起点找终点,而应当从终点倒序找到起点,这样寻找路径的过程是保证有正确解的。从终点开始,访问当前结点A的上下左右四个位置B,正确的点为 B点的值=A点的值-1 。记录从终点到起点的路径上各点坐标,找到起点后,从起点开始输出路径,这一过程用栈记录很方便

代码

1、结构体表示地图上的点

struct address
{
 int x;
 int y;
  operator==(address& b)
 {
  return x == b.x && y == b.y;
 }
};

2、bfs函数

int row[4]= { 0,0,1,-1 };
int col[4]= { 1,-1,0,0 };

void bfs_find(address begin, address end, int m[][5], int x, int y)
{
    //从2开始
    m[begin.x][begin.y] = 2;
    address temp;
    address fa;
    linkedQueue<address> arr;
    arr.push(begin);
    while (!arr.empty())
    {
         fa= arr.front();
         arr.pop();
         for (int i = 0; i < 4;i++)
     {
             temp.x= row[i] + fa.x;
             temp.y= col[i] + fa.y;//上下左右四个方位 
             if (temp.x >= 0&& temp.x < x && temp.y >= 0 && temp.y < y)//判断是否出局 
             {
                  if (m[temp.x][temp.y] ==0)
                  {
                      m[temp.x][temp.y] = m[fa.x][fa.y] + 1;//标记距离 
                      arr.push(temp);
                  }
             }
         }
         if (temp.x == end.x && temp.y== end.y)
             break;
    }
}

3、用栈记录输出路径

void output(address begin, address end, int m[][5], int x, int y)
{
    stack <address> record;
    address temp, fa;
    temp= end;
    fa= end;
    record.push(end); //只能倒序找,所以要记录
    while (1)
    {
        if (temp == begin)
         {
            break;
         }
         for (int i = 0; i < 4;i++)
         {
             temp.x= row[i] + fa.x;
             temp.y= col[i] + fa.y;
             if (temp.x < 0 ||temp.x >= x || temp.y < 0 ||temp.y >= y)//判断是否出局 
             {
                  continue;
             }
             if (m[temp.x][temp.y] ==(m[fa.x][fa.y] - 1))
             {
                  record.push(temp);
                  fa= temp;
                  break;
             }
         }
    }

    while(!record.empty())
    {
         cout << '(' << record.top().x << ',' << ' ' << record.top().y <<')' << endl;
         record.pop();
    }
}

4、

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
using namespace std;

struct address
{
    int x;
    int y;
    bool operator==(address& b)
    {
        return x == b.x && y == b.y;
    }
};

 

template<class T>
class queue
{
public:
    virtual ~queue() {}
    virtual bool empty() const = 0;
    virtual int size() const = 0;
    virtual T& front() = 0;
    virtual T& back() = 0;
    virtual void pop() = 0;
    virtual void push(const T& theElement) = 0;
};
template<class T>
struct chainNode
{
    T element;
    chainNode* next;
};


template<class T>

class linkedQueue : public queue <T>

{

 

    chainNode<T>* queueFront;

    chainNode<T>* queueBack;//需要在构造函数里初始化不知道为什么

    int queuesize;

public:

    bool empty() const { return queuesize == 0; }//判断是否为空

    int size() const { return queuesize; }//返回队列大小

    linkedQueue()

    {

         queueFront= NULL;

         queueBack= NULL;

         queuesize= 0;

    }

    T& front()//返回头元素

    {

         if (queuesize != 0)

             returnqueueFront->element;

         else

             cout<< "queue is null!";

    }

    T& back() //返回尾元素

    {

         if (queuesize != 0)

             returnqueueBack->element;

         else

             cout<< "queue is null!";

    }

    void pop()//弹出头元素

    {

 

         if (queuesize > 1)

         {

             chainNode<T>* temp =queueFront;

             queueFront= queueFront->next;

             delete temp;

             queuesize--;

         }

         else if (queuesize == 1)//队列大小为1,头尾指针都要置空

         {

             queueBack= NULL;

             delete queueFront;

             queuesize--;

             queueFront= NULL;

         }

         else

             cout<< "queue is null!";

    }

    void push(const T& theElement)

    {

         if (queuesize == 0)//若队列为空,创建新节点,并使头尾指针都指向该节点

         {

             queueFront= new chainNode<T>;

             queueFront->element= theElement;

             queueBack= queueFront;

             queuesize++;

         }

         else

         {

             queueBack->next= new chainNode<T>;

             queueBack= queueBack->next;

             queueBack->element= theElement;

             queuesize++;

         }

    }

 
    ~linkedQueue()
    {
         while (queuesize != 0)
         {
             pop();

         }

    }

};

 

void readmap(int a[][5], int x, int y)//读入地图 

{

    for (int i = 0; i < x; i++)

         for (int j = 0; j < y; j++)

         {

             cin>> a[i][j];

         }

}

 

int row[4]= { 0,0,1,-1 };

int col[4]= { 1,-1,0,0 };


void bfs_find(address begin, address end, int m[][5], int x, int y)

{
    //从2开始

    m[begin.x][begin.y] = 2;

    address temp;

    address fa;

    linkedQueue<address> arr;

    arr.push(begin);


    while (!arr.empty())

    {

         fa= arr.front();

         //       cout<< "size is " << arr.size();

         //       cout<< "fa is" << fa.x << fa.y << endl;

         arr.pop();

         for (int i = 0; i < 4;i++)
         {

             temp.x= row[i] + fa.x;

             temp.y= col[i] + fa.y;//上下左右四个方位 

             if (temp.x >= 0&& temp.x < x && temp.y >= 0 && temp.y < y)//判断是否出局 

             {

                  if (m[temp.x][temp.y] ==0)
                  {
                      m[temp.x][temp.y] = m[fa.x][fa.y] + 1;//标记距离 

                      arr.push(temp);
                  }
             }

         }

         if (temp.x == end.x && temp.y== end.y)

            break;

    }
 

}

void output(address begin, address end, int m[][5], int x, int y)
{

    stack<address> record;

    address temp, fa;

    temp= end;

    fa= end;

    record.push(end); //只能倒序找,所以要记录

 

    while (1)

    {

         if (temp == begin)

         {

             break;

         }

         for (int i = 0; i < 4;i++)

         {

             temp.x= row[i] + fa.x;

             temp.y= col[i] + fa.y;

             if (temp.x < 0 ||temp.x >= x || temp.y < 0 ||temp.y >= y)//判断是否出局 
             {
                  continue;
             }
            if (m[temp.x][temp.y] ==(m[fa.x][fa.y] - 1))
             {

                  record.push(temp);
                  fa= temp;
                  break;
             }
         }
    }


    while(!record.empty())
    {
         cout<< '(' << record.top().x << ',' << ' ' << record.top().y << ')' << endl;
         record.pop();
    }

}

 

int main(int argc, char** argv) {

    int map[5][5];

    memset(map,0, sizeof(map));//初始化二维数组 

    readmap(map,5, 5);

    address Begin, End;

    Begin.x= 0;

    Begin.y= 0;

    End.x= 4;

    End.y= 4;

    bfs_find(Begin,End, map, 5, 5);//广度优先搜索找到最短路径 

    output(Begin,End, map, 5, 5);//输出最短路径 

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值