八皇后问题

1.   问题:在棋盘上放置8个皇后,使得它们互不攻击,每个皇后的攻击范围为同行同列和同对角线,要求找出所有解。

思路:不难发现恰好每行每列放置一个皇后,如果用C[x]表示第x行皇后的列编号,则问题变成了全排列生成的问题。

流程图如下:


代码实现:

#include<iostream>
#include<cstdio>
using namespace std;
int n,cnt;
int C[100];
void search(int row){
	if (row == n)cnt++;
	else for (int i = 0; i < n; i++){//尝试i~n-1列
		bool ok = true;
		C[row] = i;
		for (int j = 0; j < row;j++)
		if (C[j] == C[row] || row - C[row] == j - C[j] || row + C[row] == j + C[j]){
			ok = false; break;
		}
		if (ok)search(row + 1);
	}
}
int main()
{
	cin >> n;
	search(0);
	cout << cnt << endl;
	system("pause");
	return 0;
}

2.   八皇后问题的优化

由于每次判定能不能在该列放入当前皇后,而判断的过程都要检查是否与已经放入的皇后冲突。为了提高程序效率,可以分别用三个一维数组记录已经占用的列、主对角线和副对角线。把它们合并为一个二维数组vis[2][]。

那么如果该位置可以放入当前皇后,那么在递归调用前应该修改vis[2][],使得该递归之路都知道该列、该主对角线和该副对角线已经被占用。但是,在回溯的过程,应该把vis[2][]数组还原为原来的样子,以便于解答树的横向拓展。

具体的函数可以为下面:

#include<iostream>
#include<cstdio>
using namespace std;
int n,cnt;
int vis[2][100];
void search(int row)
{
	if (row == n)cnt++;
	else for (int i = 0; i < n; i++){
		if (!vis[0][i] && !vis[1][row-i+n] && !vis[2][row+i]){
			vis[0][i] = vis[1][row-i+n] = vis[2][row+i] = 1;
			search(row + 1);
			vis[0][i] = vis[1][row-i+n] = vis[2][row+i] = 0;
		}
	}
}
int main()
{
	cin >> n;
	search(0);
	cout << cnt << endl;
	system("pause");
	return 0;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值