简单易懂DFS(二)抽象DFS

像迷宫这一类的题目使用到的dfs算法都是比较容易想象出搜索过程中的,而有些问题不是那么容易就能想象出搜索过程的,我们把这类问题称之为抽象形式的dfs。

例1:给定n个整数,要求选出K个数,使得选出来的K个数的和为sum。

对于形如这样问题,并没有很明显的地图让你来进行搜索;但依然可以借助dfs来解决这个问题。

  1. 对于每一个数,枚举选或者不选两种情况。
  2. 我们在搜索过程中,用S来记录当前选择的数值总和,k来记录选择的数的个数,deep表示当前正在枚举第几个数是否选择。
  3. 在第一层dfs的时候,我们可以枚举是否选第一个数,如果选择第一个数则让S加上第一个数且k加1,dfs进入下一层;否则dfs直接进入到下一层。
  4. 在第二层,对于第二个值做同样的处理,dfs的过程中记录已经选取的数的个数,如果已经选取了k个数,判断S值是否等于sum。对于每一层,我们都有两个选择–选和不选。不同的选择,都会使搜索进入不同的分支继续搜索

借助上面的dfs思想,可以写出如下代码:

#include <iostream>
using namespace std;
int a[40];
int n, k, sum, ans;
//i表示选择第i个数,cnt记录选择的个数,s表示选取数的和
void dfs(int i, int cnt, int s) {
	if (i == n) {
		if (cnt == k && s == sum) {
			ans++;
		}
		return;
	}
	dfs(i + 1, cnt, s); //不选该数
	dfs(i + 1, cnt + 1, s + a[i]); //选择该数
}
int main() {
	cin >> n >> k >> sum;
	for (int i = 0; i < n; ++i) {
		cin >> a[i];
	}
	ans = 0;
	dfs(0, 0, 0);
	cout << ans << endl;
	return 0;
}

input:

5 3 9
1 2 3 4 5

output:

2

例2:N皇后问题

N皇后问题是一个经典的问题,在一个N∗N的棋盘上放置N个皇后,每行港后放置一个并使其不能互相攻击(同一行,同一列、同一斜线上的皇后都会自动攻击)
在这里插入图片描述
上图就是一个合法的8皇后的解。N皇后问题是指:计算一共有多少种的方法放置N个皇后

这道题也可以借助dfs的思想,即先判断第一行填充哪些位置,然后根据第一行填充的位置将棋盘上不能填充的位置标记(不能同一行、同一列、同一斜线),再填充下一行,每次根据之前状态的填充位置进行填充下一行,直到每一行都有皇后为止。

标记棋盘上不能填充的位置,可以使用下面这种比较巧妙地方法:

//col标记列,x1标记正斜线,x2标记反斜线
int col[10], x1[20], x2[20];
col[i] = x1[r + i] = x2[r - i + n] = true;  
//r表示填充第r行,(r, i)表示放置的位置,r + i 表示正斜线,r - i + n表示反斜线
//可以简单的推理一下,每一条正斜线的r + i都相等,反斜线的r - i都相等,为了
//防止负数,加一个n确保其为正数

然后根据上面的思路,可以写出如下代码:

#include <iostream>
using namespace std;
int n;
int ans;
bool col[10], x1[20], x2[20];
bool check(int r, int i) {
	return !col[i] && !x1[r + i] && !x2[r - i + n];
}
void dfs(int r) {
	if (r == n) {
		ans++;
		return;
	}
	for (int i = 0; i < n; ++i) {
		if (check(r ,i)) {
			col[i] = x1[r + i] = x2[r - i + n] = true;
			dfs(r + 1);
			col[i] = x1[r + i] = x2[r - i + n] = false;
		}
	}
}
int main() {
	scanf("%d", &n);
	dfs(0);
	cout << ans << endl;
	return 0;
}

input:

4

output:

2

input1

8

output2:

92

理解抽象形式的dfs的问题求解,有助于加强对于dfs的理解
理解了n皇后问题的求解可以尝试2n皇后问题的求解:可以考虑这样的思路,将其分解为n皇后问题来求解,再传入一个参数p进行dfs,根据传入的参数p的值来判断放置黑皇后或白皇后(此思路仅供参考)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值