N皇后问题

N皇后问题## 标题
一:题目介绍
八皇后问题是一个古老而著名的问题,是回溯算法的经典问题。该问题是十九世纪著名的数学家高斯在1850年提出的:在8*8的国际象棋棋盘上,安放8个皇后,要求没有一个皇后能够“吃掉”任何其它一个皇后,即任意两个皇后不能处于同一行,同一列或者同一条对角线上,求解有多少种摆法。

高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法得到结论,有92种摆法。

本实验拓展了N皇后问题,即皇后个数由用户输入。

八皇后在棋盘上分布的各种可能的格局数目非常大,约等于2的32次方种,但是,可以将一些明显不满足问题要求的格局排除掉。由于任意两个皇后不能同行,即每行只能放置一个皇后,因此将第i个皇后放在第i行上,这样在放置第i个皇后时,只要考虑它与前i-i个皇后处于不同列和不同对角线位置上即可。
二:算法思想
解决这个问题需要采用回溯法,首先将第一个皇后放置在第一行第一列,然后,依次在下一行放置一个皇后,直到八个皇后全部放置安全。在放置每个皇后时,都依次对每一列进行检测,首先,检测放在第一列是否已经放置皇后,如不冲突,则将皇后放置在该列,否则,选择该行的下一列进行检测。如该行的八列都冲突,则返回到上一行,重新选择位置,依次类推。

特殊想法;
(1)要素一:解空间
一般想法:利用二维数组,用【i】【j】确定一个皇后的位置!
优化:利用约束条件,只需要一维数组即可!
x:array[1…n] of integer;
x[i]:i表示第i行皇后
x[i]表示第i行上皇后放在第几列
这么说好理解一点
第一行x[0]=1;放在第一列
第二行x[1]=3;放在第三列
第三行x[2]=4;放在第四列
第五行x[3]=2;放在第二列
这样有些讨巧。还是决定不用了。
(2)要素二:约束条件
一维数组的情况:

首先不同行:x[i]中的i不能出现两次;
不同列l;x[i]的值能出现两次;
不同对角线:abs[x[i]-x[j]]==abs[i-j];

二维数组的情况:

首先不同行:x[i][j]中的i 不能出现两次;
不同列 :x[i][j]中的j 不能出现两次;
不同对角线:abs[i-i]==abs[j-j]

(3)状态树
将搜索过程中的每个状态用树的形式表示出来!
画出状态数对书写程序有很大的帮助!
(4)回溯
最终要的就是要有回溯思想,否则你是不是皇后就死了,就跟我们下象棋的时候的悔棋是一样的。

程序的结束条件:一组解:设标志,找到一解后更改标志,以标志作为结束循环的条件,所有解:K=0;
判断约束函数判断第k个后能不能放在x[k]处两个皇后不能放在统一斜线上:
若2个皇后放置的位置分别是(i,j)和(k,l),且i-j=k-1或i+j=k+1,则说明这2个皇后处于同一斜线上。

第二天想到的思想:我们可以先确定皇后在第几行然后在确定皇后在第几列的问题。也就是在dfs中的for语句和if语句。
三:算法实现

#include<iostream>
#include<cmath>
using namespace std;
int n;
int x[100]={0};
int cnt = 0;

int output()
{
	cout << "第"<< cnt<<"种放置方法为:"<<endl;
	for(int i=1;i<=n;i++)
	{
		cout<<"("<<i<<","<<x[i]<<")"<<endl;
	 } 
}

bool place(int k)
{
	for(int j=1;j<k;j++)
	if(x[j]==x[k]||abs(j-k)==abs(x[j]-x[k]))
	{
		return 0;
	}
	else 
	{
		return 1;
	}
}

int dfs(int t,int n)
{
	if(t>n)
	{
		cnt++;
		output();
	}
	else
	{
		for(int i=1;i<n;i++)
		{
			x[t]=i;
			if(place(t)==1)
			{
				dfs(t+1,n);
			}
		}
	}
	
 } 
int main()
{
	cin >> n;
	cout << n << "皇后的放置方法为"<<endl;
	dfs(1,n);
	return 0; 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值