洛谷題集——01迷宮(dfs、bfs)

01迷宮

有一個僅由數字00與11組成的n×n格迷宮。若你位於一格0上,那麼你可以移動到相鄰4格中的某一格1上,同樣若你位於一格1上,那麼你可以移動到相鄰4格中的某一格0上。
你的任務是:對於給定的迷宮,詢問從某一格開始能移動到多少個格子(包含自身)。

輸入格式
第1行爲兩個正整數n,m。
下面n行,每行n個字符,字符只可能是0或者1,字符之間沒有空格。
接下來m行,每行2個用空格分隔的正整數i,j,對應了迷宮中第i行第j列的一個格子,詢問從這一格開始能移動到多少格。

輸出格式
m行,對於每個詢問輸出相應答案。

輸入輸出樣例
輸入
2 2
01
10
1 1
2 2
輸出
4
4


BFS版本

該題是查詢某一塊符合條件的個數,而且是多組輸入。
若用到單純BFS的思路的話,很容易造成重複查詢的情況,導致超時。
爲了避免超時,這裏應當用BFS+記憶化剪枝的方式提高效率。

#include<bits/stdc++.h>
using namespace std;
int mg[1010][1010], n, m;

//防止重複記格 
bool flag[1010][1010]={false};

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

struct node{
	int a;
	int b;
}Node, top;

bool judge(int xi, int yi, int x, int y)
{
	if(x<=0||y<=0||x>n||y>n)
	return false;
	if((mg[xi][yi]==1&&mg[x][y]==0)||(mg[xi][yi]==0&&mg[x][y]==1))
	return true;	
	return false;
}

map<int, int> mm;

int main()
{
	char ch;
	cin>>n>>m;
	
	for(int i=1; i<=n; i++)
	for(int j=1; j<=n; j++)
	{
		cin>>ch;
		if(ch=='0')
		mg[i][j]=0;
		else
		mg[i][j]=1;
	}
	
	while(m--)
	{
		int x, y, sum=0;
		cin>>x>>y;
		if(mg[x][y]==0||mg[x][y]==1)
		{
			queue<node> q;
			Node.a=x;
			Node.b=y;
			q.push(Node);
			while(!q.empty())
			{
				top=q.front();
//				cout<<top.a<<" "<<top.b<<endl;
				int xi=top.a;
				int yi=top.b;
				for(int i=0; i<4; i++)
				{
					if(judge(xi, yi, xi+X[i], yi+Y[i]))
					{
						Node.a=xi+X[i];
						Node.b=yi+Y[i];
						q.push(Node);
					}
				}
			//	防止重複記格 
				if(flag[xi][yi]==false)
					sum++;
				flag[xi][yi]=true;
				mg[xi][yi]=m+100010;
				q.pop();
			}
			mm[m+100010]=sum;
		}
/*		for(int i=1; i<=n; i++)
		{
			for(int j=1; j<=n; j++)
			cout<<mg[i][j]<<" ";
			cout<<endl;
		}*/
		cout<<mm[mg[x][y]];
		if(m!=0) cout<<endl;
	}
	
	return 0;
} 
DFS版本

相比與該題的BFS版本,個人認爲DFS思路較爲巧妙,而BFS版本就是單純的模板改良。
主要思路:將要查詢的方格i,通過DFS試探的方式查找出符合條件該方塊周圍符合的方塊數,同時利用flag二維數組標記訪問過的方格,防止重複訪問(剪枝),並最終結果記錄在ans[i]中。

#include<bits/stdc++.h>
using namespace std;
int n, m;
int flag[1010][1010];
int mg[1010][1010];
int ans[100010];
int X[4]={0, 0, 1, -1};
int Y[4]={1, -1, 0, 0};

void dfs(int x, int y, int i)
{
	if(x<1||y<1||x>n||y>n) return;
	ans[i]++;
	flag[x][y]=i;
	for(int j=0; j<4; j++)
	if(mg[x+X[j]][y+Y[j]]!=mg[x][y]&&flag[x+X[j]][y+Y[j]]==-1)
		dfs(x+X[j], y+Y[j], i);
}

int main()
{
	cin>>n>>m;
	for(int i=1; i<=n; i++)
	for(int j=1; j<=n; j++)
	{
		char ch;
		cin>>ch;
		if(ch=='1') mg[i][j]=1;
		else mg[i][j]=0;
	}
	
	memset(flag, -1, sizeof(flag));
	memset(ans, 0, sizeof(ans));
	for(int i=0; i<m; i++)
	{
		int x, y;
		cin>>x>>y;
		if(flag[x][y]==-1)
		{
			flag[x][y]=i;
			dfs(x, y, i);
		}
		else
			ans[i]=ans[flag[x][y]];
	}
	for(int i=0; i<m; i++)
	{
	    cout<<ans[i];
	    if(i!=m-1) cout<<endl;
	}
	return 0;
}

總結

在該題中,在運行效率上dfs代碼比bfs代碼要高,但在存儲空間上bfs代碼比dfs代碼要小,各有所長。

希望能夠將自己的一些學習經驗分享給有需要的人。
我是小鄭,一個堅持不懈的小白。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章