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;
}