N皇后问题c++

本文介绍了如何使用搜索与回溯算法解决经典的N皇后问题,即在N×N的棋盘上放置N个皇后,使得任意两个皇后不在同一行、同一列或同一对角线上。通过递归地尝试不同位置并回溯不合适的位置,找到所有可能的解决方案。文章提供了详细的解题思路,包括边界条件和检查皇后位置合法性的方法,并给出了C++代码实现。重点在于理解搜索与回溯策略在解决约束优化问题中的应用。
摘要由CSDN通过智能技术生成

题目描述(洛谷P1219)

一个如下的6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列2 4 6 1 3 5 来描述,第i个数字表示在第i行的相应位置有一个棋子,如下:

行号 1\ 2\ 3\ 4\ 5\ 6

列号 2\ 4\ 6\ 1\ 3\ 5

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 3 个解。最后一行是解的总个数。

解题思路

        作为基础搜索题,N皇后的搜索方式可以类比运用到有关二维数组的搜索题中

        其核心操作就是在递推操作的同时加入了回溯,方便于搜索的全覆盖

        基本思想就是确定一个皇后的位置,然后按一定顺序确定下一个皇后位置

        如果没有合适的位置则说明已确定的皇后位置无解

        应迭代或回溯更换改皇后位置

基本思路

        要实现二维平面内的移动,首先要明确边界的限定

1.行数  l <=n 如果最后一行l=1能够确定皇后的位置,则说明n行皇后位置全部确定(即可输出);

2.根据(1.)的描述可知,当操作到第i行时,代表前i+1行已经确定

        其次要满足题中“使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子”的条件

        这里事先声明第i行已确定位置的皇后在第p[i]列

        在检查该条件是否成立时,选择了按行递增检查

1.据此,我们只需在检查前i-1行时,检查该行第k列是否有皇后(k==p[j]?),如果有,则证明第k列有皇后,不可再放置

2.为确定对角线是否有皇后,只需确定第i行与检查行j之差(i-j)是否等于列之差(k-p[j])即i-j==k-p[j]?

3.无需确定是否同一行,因为已知前i-1行有皇后放置

        输出时,输出第i行的皇后列数p[i]

代码实现 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 1000010

using namespace std;

inline int read(){
	int x=0;
	int f=1;
	char ch;
	ch=getchar();
	while(ch>'9'||ch<'0'){
		if(ch='-') f=-f;
		ch=getchar();
	}
	while(ch<='9'&&ch>='0'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*f;
}

int n;//n*n棋盘 
int cnt;//解的个数 
int p[1005];//第i行皇后的列数 

void print(int m){
	cnt++;
	if(cnt<=3){
	for(int i=1;i<=m;i++){
		cout<<p[i]<<' ';//输出第i行皇后的列数 
	}
	cout<<endl;
	}
	return ;
}

bool find(int i,int k){//判断(i,k)位置是否合法 
	int j=1;
	while(j<i){//检查前i-1行 
		if(p[j]==k||abs(j-i)==abs(p[j]-k)){//判断是否为同一列或者对角线 
			return 0;
		}
		j++;
	}
	return 1;
}

inline void place(int i,int k){
	int h;
	if(i>n){//显然前n行皇后都填过了,直接输出 
		print(n);
	}
	else{
		for(h=1;h<=n;h++)
		{
			if(find(i,h)){//判断是否合法 
				p[i]=h;//如果合法,记录第i行皇后放在第h列 
				place(i+1,k);//寻找下一个皇后 
			}
		}
	}
}

int main(){
	n=read();
	place(1,n);
	printf("%d",&cnt);
	return 0;
}

一些话

        CSP复赛快开始了,复习复习搜索是有必要的 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值