深搜与宽搜(DFS与BFS)

本文介绍了使用深度优先搜索(DFS)解决八皇后问题的方法,以及在其他问题(如三角形、生日蛋糕和棋盘填色)中的应用,强调了深度搜索的无剪枝特性,展示了如何通过递归和回溯实现算法过程。
摘要由CSDN通过智能技术生成

深搜无剪枝等于暴力搜索

宽搜有最短路径的性质

八皇后问题

a[i] 表示 第i行的皇后放在第a[i]列上

b[i] 有true和false两种取值

  •         true:第i列可用
  •         false:第i列不可用

逐行放置皇后

对角线如何判断?(出现负数用map)

#include<bits/stdc++.h>
using namespace std;
#define int long long
// #define max(a,b) ((a)>(b))?a:b
// #define min(a,b) ((a)<(b))?a:b
#define pb push_back
vector<int> a(9,0);
vector<bool> b(9,true), c(30,true);
map<int, bool> mp;
int ans = 0; // 方案数
// n代表放置第几个皇后
void dfs(int n){
	//八个皇后都已放好
	if(n==9) {
		ans++;
		for (int i=1; i<=8; i++) {
			cout << a[i] << ' ';
		}
		cout << '\n';
	};
	// 枚举放在每一列的情况
	for (int i=1; i<=8; i++) {
		// 可放
		if (b[i] && c[n+i] && mp[n-i]) {
			a[n] = i;
			b[i] = c[n+i] = mp[n-i] = false;
			// 放下一个
			dfs(n+1);
			// 深度搜索到头回溯
			a[n] = 0;
			b[i] = c[n+i] = mp[n-i] = true;
		}
	}
}
signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	// 对角线判断可能出现负数,所以用map
	for (int i=0; i<=30; i++) {
		mp[i] = true;
		mp[-i] = true;
	}
	dfs(1);
	cout << ans;
	return 0;
}

Triangle - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
using namespace std;
#define int long long
// #define max(a,b) ((a)>(b))?a:b
// #define min(a,b) ((a)<(b))?a:b
#define pb push_back
int ans1 = 0, ans2 = 0;
vector<bool> b(5, true);
vector<int> c(4,0), a(5,0); // 存选出的木棒
// x 是 选第几个木棒
void dfs(int x) {
	// 选木棒
	if (x==4) {
		// cout << c[1] << c[2] << c[3] << '\n';
        // 一定要开新数组,否则排序会打乱c数组的顺序,影响回溯
		vector<int> d = c;
		sort(d.begin()+1, d.end());
		if (d[1]+d[2]>d[3]) {
			ans1 = 1;
		}
		else if (d[1]+d[2]==d[3]) ans2 = 1;
		return;
	}
	for (int i=1; i<=4; i++) {
		// i能选
		if (b[i]) {
			c[x] = a[i];
			b[i] = false;
			x++;
			dfs(x);
			x--;
			b[i] = true;
			c[x] = 0;
		}
	}
}
signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	for (int i=1; i<=4; i++) {
		cin >> a[i];
	}
	dfs(1);
	if (ans1) cout << "TRIANGLE";
	else if (ans2) cout << "SEGMENT";
	else cout << "IMPOSSIBLE";
	return 0;
}


Far Relative’s Birthday Cake - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
using namespace std;
#define int long long
// #define max(a,b) ((a)>(b))?a:b
// #define min(a,b) ((a)<(b))?a:b
#define pb push_back
int n,i,j;
int ans = 0; // 幸福指数
char s[105][105]; //地图数组
vector<vector<bool>> vis(105,vector<bool>(105,true)); //访问数组
bool check(int x, int y) {
	if (x == i && y <= n) return 1; //在同一行
	if (x <= n && y == j) return 1; // 在同一列
	return 0;
}
// 当前位置的横纵坐标x、y
void dfs(int x, int y) {
	// x、y超过范围返回
	if (!check(x,y)) return;
	// 当前位置不是(i,j)且为'C'
	if (s[x][y] == 'C' && (x!=i || y!=j)) {
		// cout << i << j << x << y << '\n';
		ans++;
	}
	// 继续搜索
	dfs(x+1, y); // 下面一格
	dfs(x, y+1); // 右面一格
	// 无需回溯
}
signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i=1; i<=n; i++) 
		for (int j=1; j<=n; j++)
			cin >> s[i][j];
	// 双重循环找'C', 找到就DFS。
	for (i=1; i<=n; i++) {
		for (j=1; j<=n; j++) {
			// 搜索(i,j)以下和以右
			if (s[i][j] == 'C') {
				vis[i][j] = false; //防止和自身配对使得ans+1
				dfs(i, j);
			}
		}
	}
	cout << ans;
	return 0;
}

DZY Loves Chessboard - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
using namespace std;
#define int long long
// #define max(a,b) ((a)>(b))?a:b
// #define min(a,b) ((a)<(b))?a:b
#define pb push_back
int n,m,i,j;
char s[105][105]; //地图数组
vector<vector<bool>> vis(105,vector<bool>(105,true)); //访问数组
// 当前位置的横纵坐标x、y, i表示当前应该放哪种棋子
void dfs(int x, int y, int i) {
	vis[x][y] = false; //访问过不会再访问
	// cout << x << ' ' << y << '\n';
	// x、y超过范围返回
	if (x>n || y>m || x<1 || y<1) return;
	// 当前位置不是(i,j)且为'C'
	if (s[x][y] == '.') {
		if (i==0) // 0放白
			s[x][y] = 'W';
		else // !0放黑
			s[x][y] = 'B';
	}
	// 未访问到的点就继续搜索
	if (vis[x+1][y]) dfs(x+1, y, !i); // 下面一格放!i
	if (vis[x][y+1]) dfs(x, y+1, !i); // 右面一格放!i
	if (vis[x-1][y]) dfs(x-1, y, !i); // 上面一格放!i
	if (vis[x][y-1]) dfs(x, y-1, !i); // 左面一格放!i
	// 无需回溯
}
signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i=1; i<=n; i++) 
		for (int j=1; j<=m; j++)
			cin >> s[i][j];
	dfs(1,1,0);
	for (int i=1; i<=n; i++) {		
		for (int j=1; j<=m; j++){	
			cout << s[i][j];
		}
		cout << '\n';
	}
	return 0;
}

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值