蓝桥杯-N皇后(DFS)

0.题目

【题目描述】

有一个N*N的矩阵棋盘和N个棋子,现在需要将N个棋子按要求放置在矩阵方格中。

要求:

1、任意两颗棋子不能在同一行

2、任意两个棋子不能在同一列

3、任意两个棋子不能在同一对角线上(下面的红线都是对角线)

根据以上要求,问N个棋子放置到N*N矩阵中有多少种放置方案?

【输入描述】

输入一个正整数N(1<N<11),表示N*N的矩阵方格和N个棋子数量。

【输出描述】

输出N个棋子按要求放置到N*N的矩阵中,有多少种放置方案?

1.题解

1.1 DFS搜索

思路

对于不能同行,整体按行顺序从上到下进行遍历(外层循环)
难点主要是纠正同列和对角线的情况,利用记忆化存储存储之前节点实际皇后摆放位置,然后和当前皇后位置进行比较
如果发生冲突,放弃该位置; 如果不发生冲突, 可以选择该位置,也可以不选择该位置,同时更新当前chosen数组的值即可

代码

#include<bits/stdc++.h>
using namespace std;

// 表示第n行的皇后摆放的列位置
int chosen[11] = {-1};
int ans = 0;
int n;

// x表示当前已经选择了x个
void DFS(int x) {
	if (x == n + 1) {
		ans++;
		return;
	}

//	// 选择该行放置的列位置i, [x][i],
//	for (int i = 1; i <= n; i++) {
//		if(x == 1) {
//			chosen[x] = i;
//			DFS(x + 1);
//		} else {
//			// 遍历之前的行, [j][chosen[j]]
//			for (int j = 1; j < x; j++) {
//				if ((chosen[j] != i) && (abs(chosen[j] - i) != abs(x - j))) {
//					// 选择该位置
//					chosen[x] = i;
//					DFS(x + 1);
//					// 不选择该位置
//					chosen[x] = -1;
//				}
//			}
//		}
//	}

	// 选择该行放置的列位置i, [x][i],
	for (int i = 1; i <= n; i++) {
		bool conflict = false;
		chosen[x] = i;
		// 遍历之前的行,判断有无冲突 [j][chosen[j]]
		for (int j = 1; j < x; j++) {
			if((chosen[j] == i) || (abs(j - x) == abs(chosen[j] - chosen[x]))){
				conflict = true;
				break;
			} 
		}
		// 没有冲突 
		if(!conflict){
			DFS(x+1);
		}

	}
}

int main() {
	cin >> n;
	DFS(1);
	cout << ans;
	return 0;
}

优化版本

主要是封装了函数,使其更符合普遍模板

#include <bits/stdc++.h>
using namespace std;

int chosen[11] = {0};
int ans = 0;
int n;

// 判断是否会发生冲突(剪枝) 
int PD(int k){
	for(int i = 1; i < k; i++){
		if(abs(k-i) == abs(chosen[k]-chosen[i])){
			return 0;
		} else if(chosen[k] == chosen[i])
			return 0;
	}
	return 1;
} 

// 判断返回条件 
bool check(int a){
	if(a > n){
		ans++;
	}
	else return 0;
	return 1;
} 

void DFS(int x) {
    if (check(x)) {
		return;
    }
    
    // 尝试在第 x 行的每一列放置皇后 [x][i];
    for (int i = 1; i <= n; i++) {
		chosen[x] = i; 
		// 判断这一步是否冲突
		if(PD(x)) {
			DFS(x+1);
		}else{
			// 不需要清零,每次开头的chosen[x] = i;就可以实现刷新 
//			chosen[x] = 0;
			continue;
		}
    }
}

int main() {
    cin >> n;
    DFS(1);
    cout << ans << endl;
    return 0;
}

posted @ 2024-04-10 18:23  DawnTraveler  阅读(59)  评论(0编辑  收藏  举报