1. 程式人生 > >深度優先搜尋的學習

深度優先搜尋的學習

解決深度優先搜尋關鍵在於“當下該如何做”到”下一步該如何做“。

通常是把每一種方法都嘗試一遍,當這一步解決後進行下一步。

基本模型:

void dfs(int step)
{
  判斷邊界
  嘗試每一種可萌
  for(int i=1;i<=n;i++){
     繼續下一步
   }
  返回
}

舉例:

輸入一個數n,輸出1~n的全排列

/*全排列問題,舉個例子就是有幾張牌放在幾個不同盒子裡,有多少種情況*/
#include<iostream>
using namespace std;
int a[10], book[10], n;//a是牌,book是盒子,當book為1時說明有牌
void dfs(int step) {
	if (step == n + 1) {//當在第n+1和盒子時說明已經排完
		for (int i = 1; i <= n; i++) {
			cout << a[i];//輸出牌
		}
		cout << endl;
		return;//返回上一次呼叫時的dfs函式
	}
	for (int i = 1; i <= n; i++) {
		if (book[i] == 0) {//判斷是否可以放牌
			a[step] = i;
			book[i] = 1;//標記
			dfs(step + 1);//遞迴,進行下一個盒子
			book[i] = 0;//每次放完牌記得要清零
		}
	}
	return;
}
int main() {
	cout << "輸入盒子個數" << endl;
	cin >> n;
	dfs(1);//從第一個盒子開始
	return 0;
}

再舉個例子:

有數字1~9,使得???+???+???=???成立

/*與盒子裡放牌是一個道理*/
#include<iostream>
using namespace std;
int a[10], book[10], total = 0;//total是有幾種可能
void dfs(int step) {
	if (step == 10) {
		if (a[1] * 100 + a[2] * 10 + a[3] + a[4] * 100 + a[5] * 10 + a[6] == a[7] * 100 + a[8] * 10 + a[9]) {
			total++;
			cout << a[1] << a[2] << a[3] << "+" << a[4] << a[5] << a[6] << "=" << a[7] << a[8] << a[9] << endl;
		}
		return;
	}
	for (int i = 1; i < 10; i++) {
		if (book[i] == 0) {
			a[step] = i;
			book[i] = 1;
			dfs(step + 1);
			book[i] = 0;
		}
	}
	return;
}
int main() {
	dfs(1);
	cout << "一共有" << total << "種可能" << endl;
	return 0;
}

利用深度優先搜尋走迷宮

/*利用深度優先搜尋走迷宮,
輸入迷宮時0代表可以走,1代表不能走,
求最短路徑*/
#include<iostream>
using namespace std;
int a[51][51];//迷宮
int book[51][51];//用來儲存走過的點
int min = 999999;//步數的最小值
int p, q,m,n;
void dfs(int x, int y, int step) {
	int next[4][2] = {//行走的座標
		{0,1},//向右
		{1,0},//向下
		{0,-1},//向左
		{-1,0}//向右
	};
	int next_x, next_y;//下一步的座標
	if (x == p&&y == q) {//判斷是否完成
		if (step < min)
			min = step;//儲存最小步數
		return;//注意要返回上一次
	}
	for (int i = 0; i < 4; i++) {//四種走法
		next_x = x + next[i][0];
		next_y = y + next[i][1];
		if (next_x < 1 || next_x>n || next_y < 1 || next_y>m)//判斷越界
			continue;
		if (a[next_x][next_y] == 0 && book[next_x][next_y] == 0) {//判斷是否能走
			book[next_x][next_y] = 1;//標記走過的點
			dfs(next_x, next_y, step + 1);//遞迴,進行下一步
			book[next_x][next_y] = 0;//清零
		}
	}
	return;
}
int main() {
	int start_x, start_y;
	cout << "輸入行和列" << endl;
	cin >> n >> m;
	cout << "輸入迷宮" << endl;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++)
			cin >> a[i][j];
	}
	cout << "輸入起始座標X" << endl;
	cin >> start_x;
	cout << "輸入起始座標Y" << endl;
	cin >> start_y;
	cout << "輸入終點座標X" << endl;
	cin >> p;
	cout << "輸入終點座標Y" << endl;
	cin >> q;
	book[start_x][start_y] = 1;//要把起點標記上,防止走重
	dfs(start_x, start_y, 0);//起始步數為零
	cout << min<<endl;
	return 0;
}


如輸入:

5 4

0 0 1 0

0 0 0 0

0 0 1 0

0 1 0 0

0  0 0 1

1 1 4 3

結果為 7