説明するための演習で、BFS共通テンプレート - 体験学習BFS

1 BFSテンプレート

階層順をトラバース

void BFS(int s){
  queue<int> q;
  q.push(s);
  while(){
    取出队首元素top;
    访问队首元素;
    将队首元素出队;
    将top的下一层结点未入队的结点全部入队,并设置为已入队;
  }
}

2つの詳細

  • 1定義のキューのQ、Sおよびキューエンキューの先頭
  • whileループ2を書く、ループ条件は、非空キューQであります
  • 3 whileループでは、最初のチームは、最初の要素のトップを取る、とするアクセスそれ(アクセス:あなたは、その出力として何も、することができます)、チームがあります
  • 4すべての要素の次の層のノードのトップチームにエンキューされていない、今+ 1それらの層の数をマークするために、ノードを設定エンキューエンキュー
  • 図5は、ループ2リターンに進み

3タイトル

M * N行列を与え、行列要素が0または1であり、位置(x、y)がその上にして四点の位置(X、Y + 1)の下、前記 (X、Y-1)、(X + 1、y)は(x-1 、y)が隣接しています。マトリックスは、(2×2必ずしも隣接していない)隣接が複数ある場合、1が「ブロック」を構成します。与えられた行列の「ブロック」の数を計算します。
以下の実施例6 * 7マトリックス、4の「ブロック」の数

Sample Input:
6 7
0 1 1 1 0 0 1
0 0 1 0 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 1 0
1 1 1 0 1 0 0
1 1 1 1 0 0 0

Sample Output:
4

リファレンスコード:

#include <cstdio>
#include <queue>

using std::queue;

const int MAXN =100;

struct node
{
    int x,y;//位置x,y
}Node;

int n, m;    //矩阵大小m,n
int matrix[MAXN][MAXN];//矩阵
bool inq[MAXN][MAXN] = {false};//记录{x,y}是否入队

int X[4] = {0, 0, 1, -1};//增量数组
int Y[4] = {1, -1, 0, 0};

bool judge(int x, int y){
    //越界
    if(x >= n || x < 0 || y >= m || y < 0) return false;
    //当前位置为0,或(x,y)已如果队
    if(matrix[x][y] == 0 || inq[x][y] == true) return false;
    return true;
}

void BFS(int x, int y){
    queue<node> Q;//定义队列
    Node.x = x; 
    Node.y = y;
    Q.push(Node);//将结点入队
    inq[x][y] = true;//设置(x,y)已入队
    while(!Q.empty()){
        node top = Q.front();//取出队首元素
        Q.pop();//队首元素出队
        for (int i = 0; i < 4; ++i)//循环四次,得到4个相邻的位置
        {
            int newX = top.x + X[i];
            int newY = top.y + Y[i];
            if(judge(newX, newY)){//如果新位置需要访问
                //将Node坐标设置为(newX, newY)
                Node.x = newX;
                Node.y = newY;
                Q.push(Node);//将结点Node入队
                inq[newX][newY] = true;//设置(newX,newY)已入过队
            }
        }
    }
}

int main(int argc, char const *argv[])
{
    scanf("%d%d", &n, &m);
    for (int x = 0; x < n; ++x)
    {
        for (int y = 0; y < m; ++y)
        {
            scanf("%d", &matrix[x][y]);//读入01矩阵
        }
    }

    int ans = 0;//存放块
    for (int x = 0; x < n; ++x)//枚举每个位置
    {
        for (int y = 0; y < m; ++y)
        {
            //如果元素为1,且未入队
            if(matrix[x][y] == 1 && inq[x][y] == false){
                ans++;
                BFS(x,y);//访问整个块,将该块的所有1的inq都标记为1
            }
        }
    }

    printf("%d\n", ans);
    return 0;
}

4タイトル

N所与*通行壁を表すラビリンスサイズmを、と「」代表的なフラット、開始するためのS、Tは、エンドポイントを表します。運動、現在位置が停止(X、Y + 1)(x、y)が(添え字は0から始まる)であり、そしてだけ上がることができるとすれば、 (X、Y-1)、(X-1、 フラットY)(X + 1、Y ) 4の位置は、ステップの最小数は、開始点T Sから終点に到達するのに必要な
...

**
... T.
私は、上記試料空腹S(2,2)のT座標(4,3)の座標

Sample Input:
5 5 	//5行5列 
..... 	//迷宫信息
.*.*.
.***.
...T.
2 2 4 3	//起点S的坐标和终点T的坐标
Sample Output:
11

リファレンスコード:

#include <cstdio>
#include <queue>

using std::queue;

const int MAXN = 100;

struct node
{
    int x, y;
    int step;    
}S, Node, T;

int m,n; //m行,n列
char maze[MAXN][MAXN];
bool inq[MAXN][MAXN] = {false};

int X[] = {0, 0, 1, -1};
int Y[] = {1, -1, 0, 0};

bool Test(int x, int y){//判断坐标(x,y)是否有效
    if(x < 0 || x >= n || y < 0 || y >= m) return false;
    if(inq[x][y] == true || maze[x][y] == '*') return false;//已入过队列,或者墙壁
    return true;
}

int  BFS(){
    queue<node> Q;//1 定义队列
    Q.push(S);//2 将起点入队
    inq[S.x][S.y] = true;
    while(!Q.empty()){
        node top = Q.front();//3 取出队首元素
        Q.pop();            //4 队首元素出队
        if(top.x == T.x && top.y == T.y){
            return top.step;//终点,直接返回最少步数
        }

        for (int i = 0; i < 4; ++i)//将top下一层结点未入队的入队,并标记为已入队
        {
            int new_x = top.x + X[i];
            int new_y = top.y + Y[i];
            if(Test(new_x, new_y) == true){
                Node.x = new_x;
                Node.y = new_y;
                Node.step = top.step + 1;//Node层数为top层数加1
                Q.push(Node);
                inq[new_x][new_y] = true;
            }
        }
    }
    return -1;//无法达到终点
}

int main(int argc, char const *argv[])
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i)
    {
        getchar();//过滤掉每个换行符
        for (int j = 0; j < m; ++j)
        {
            maze[i][j] = getchar();
        }
        maze[i][m + 1] = '\0';
    }

    scanf("%d%d%d%d", &S.x, &S.y, &T.x, &T.y);
    S.step = 0;//初始化层数为0,S到T的最小步数为0
    printf("%d\n", BFS());
    return 0;
}

5 注意点

  • BFS INQセットにノードではなく、ノード点がアクセスされたかどうかよりも、チームになっているかどうか、
  • 設定がアクセスされているのであれば、それはチームに重複ノードの多くの原因となります(ノードがチームですが、アクセスされていない、他のノードは、チームに再合流するように接合部に到達することができます)
  • STLキューキューを使用した後、チームへの要素は、ちょうどチームへの要素のコピーを入れて、チーム
    • コピーキューの要素を変更し、オリジナルの要素を変更しません
    • オリジナルの要素を変更するには、それは新年でキュー要素をコピーしません。
    • これは、(通常、構造に起因する)のバグを導入することができます
#include <cstdio>
#include <queue>

using std::queue;

struct node
{
   int data;
}a[10];

int main(int argc, char const *argv[])
{
   queue<node> q;
   for (int i = 1; i != 4; ++i)
   {
       a[i].data = i;
       q.push(a[i]);
   }

   q.front().data = 100;
   printf("%d %d %d\n", a[1].data, a[2].data, a[3].data);

   a[1].data = 200;
   printf("%d\n", q.front().data);
   return 0;
}

結果:
ここに画像を挿入説明

  • キューの要素を変更する必要性は、キュー記憶素子は、それ自体に最善ではないが、(例えば、その後標準の下に格納された配列、など)、それらの数値は改善する方法、
    上記の手順で置き換えることができます。
#include <cstdio>
#include <queue>

using std::queue;

struct node
{
    int data;
}a[10];

int main(int argc, char const *argv[])
{
    queue<int> q;
    for (int i = 1; i != 4; ++i)
    {
        a[i].data = i;
        q.push(i);
    }

    a[q.front()].data = 100;

    printf("%d\n", a[1].data);
    return 0;
}
公開された321元の記事 ウォン称賛51 ビュー40000 +

おすすめ

転載: blog.csdn.net/qq_33375598/article/details/104046582