题解-N皇后问题

本文详细探讨了N皇后问题的解决方法,通过深度优先搜索(DFS)算法,实现了在N*N的棋盘上放置N个皇后,使得彼此不受攻击的所有可能布局。介绍了基本的搜索策略,包括行、列和对角线冲突的判断,以及如何递归地搜索所有可能的解决方案。

N皇后问题

描述

在 N*N 的棋盘上放置 N 个皇后而彼此不受攻击(即在棋盘的任一行,任一列和任一对角线上 不能放置 2 个皇后),编程求解所有的摆放方法。

输入

一个数字N (3 <= N <= 10) 表示棋盘是N * N大小的。

输出

输出方案数;若无方案,则输出 “no solute!”

输入样例 1

4

输出样例 1

2

基本思路:按行DFS,枚举当前行上的每一列,选取符合条件(行、列、对角线
不冲突)的列,并对所在行、列、对角线打标记;转移到下一行继续搜索…
代码:

#include<bits/stdc++.h>
using namespace std;
int n;    
int sum=0;    
int cnt[100];  
int tmp(int cns){
    int i;
    for(i= 1;i<cns;i++){
	    if(abs(cns-i)==abs(cnt[cns]-cnt[i])||cnt[cns]==cnt[i]){  
		  return 0;	  
		}	
	} 	  
    return 1;  	 
}   
int dfs(int t){
    if(t>n&&n>0){
		sum++;    
	}else{
    	for(int i=1;i<=n;i++){ 
        	cnt[t] = i;  
        	if(tmp(t)){
        		dfs(t+1);
        	}		    
		}   
	}
    return sum;	 
}   
int main(){  
    int t;
    cin>>n;  
    t=dfs(1); 
    if(n==0){
      t=0;
	}
    cout<<t;
    return 0;   
}
### 7-5 n皇后问题 PTA 题解与算法解析 n皇后问题是经典的回溯法问题,其核心在于在n×n的棋盘放置n个皇后,使得每个皇后不受攻击。这意味着任意两个皇后不能位于同一行、同一或同一条斜线上。根据约束条件,可以通过递归回溯的方式解决此问题。 #### 约束条件 1. 每个皇后必须位于不同的:\( x_i \neq x_j \)。 2. 每个皇后不能位于同一条主对角线:\( x_i - i \neq x_j - j \)。 3. 每个皇后不能位于同一条副对角线:\( x_i + i \neq x_j + j \)。 上述条件可以等价于:\( |i - j| \neq |x_i - x_j| \)[^1]。 #### 解决方案 以下是一个基于回溯法的解决方案,适用于PTA上的n皇后问题: ```cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 20; int n, cnt = 0; int a[MAX_N]; // a[i] 表示第 i 行皇后所在的号 bool col[MAX_N], dui1[2 * MAX_N], dui2[2 * MAX_N]; // 分别表示、主对角线、副对角线是否被占用 void dfs(int u) { if (u > n) { // 如果已经放置了 n 个皇后 cnt++; printf("%4d:", cnt); for (int i = 1; i <= n; i++) { printf("%3d", a[i]); } cout << endl; return; } for (int y = 1; y <= n; y++) { if (!col[y] && !dui1[u + y] && !dui2[u - y + n]) { // 检查当前位置是否合法 a[u] = y; // 放置皇后 col[y] = true; // 标记该已被占用 dui1[u + y] = true; // 标记主对角线已被占用 dui2[u - y + n] = true; // 标记副对角线已被占用 dfs(u + 1); // 递归处理下一行 col[y] = false; // 回溯:取消标记 dui1[u + y] = false; dui2[u - y + n] = false; } } } int main() { cin >> n; if (n == 2 || n == 3 || n <= 0) { // 特殊情况处理 cout << "no answer" << endl; return 0; } dfs(1); // 从第 1 行开始放置皇后 return 0; } ``` #### 代码解析 1. **变量定义**: - `a[MAX_N]`:记录每行皇后所在的号[^2]。 - `col[MAX_N]`:标记某是否已有皇后- `dui1[2 * MAX_N]` `dui2[2 * MAX_N]`:分别标记主对角线副对角线是否已有皇后[^3]。 2. **递归函数**: - `dfs(u)`:尝试在第 u 行放置皇后,递归处理下一行- 当所有皇后都被成功放置时(即 `u > n`),输出当前解并计数。 3. **特殊情况**: - 当 \( n = 2 \) 或 \( n = 3 \) 时,不存在可行解,直接输出 "no answer"[^2]。 #### 时间复杂度 该算法的时间复杂度为 \( O(n!) \),因为需要尝试所有可能的排组合,并通过约束条件剪枝以减少不必要的计算。 --- ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值