八皇后简单版解析

1 篇文章 0 订阅
1 篇文章 0 订阅

八皇后问题

这是一个基本而又充满趣味的题,许多人第一次接触的搜索题便是这道题,相信都给各位心灵留下不可磨灭的印记,好了,不能再矫情了,这是要正经分享的,不能随意歪楼。下面直入正题。
定义在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

想来大家已经耳熟能详了,乍听起来的时候感觉难顶,这是我们智能生命体该做的事吗??(结果还真是)那么解决这道题,让我们从小问题出发,对皇后的影响力进行深入分析——首先,皇后占领一块领地后,由规则产生的影响包括了横、竖、斜上、斜下的一条道都归她管理~~(说实在的管得可真宽)~~,那么对于在一个4*4的棋盘上放置4个皇后时,同样适用。缩小分析的范围,貌似这题没那么难顶了,由分析,已经很自然的想到去存储一次皇后放置后棋盘的状态,那么很自然的就可以使用多个数组进行存储。可问题的关键,怎么去建立由棋盘上的位置到数组位置的一一映射?

这时候,以前数学学的找规律该派上用场了。行列的存储都好说,就是对对角线的处理,注意到,自左下到右上的对角线上(姑且称之为右对角线),可由横纵坐标之和映射到一整条与右对角线平行的点的连线上;而在相应的左对角线上,容易想到将横坐标转换成与右对角线等同的情形即可。话不多说,上代码。代码是针对POJ上的弱化版八皇后问题,有两个预先输入标示前两行皇后所在列数。虽然弱化,但本题的核心思想未变,处理方法也是类似的。`

#include<iostream>
#include<cstring>
using namespace std;
int row[8] = { 0 }, col[8] = { 0 }, ridia[16] = { 0 }, ledia[16] = { 0 }, board[8][8] = {0};//row为行上占领情况,col为列,ridia为右对角线(自左上向右下)ledia为左对角线;
int tex[6] = { 0 },mark=0;
bool dfs(int i) //此搜索依据题目进行了相应优化,对行数依次递深搜索
{
	if (i == 8) {
		mark = 1;
		return true;
	}
	for (int j = 0; j <= 7; j++) {
		if (col[j] == 0 && ledia[i + j] == 0 && ridia[7 - i + j] == 0) {
			col[j] = 1;
			ledia[i + j] = 1;
			ridia[7 - i + j] = 1;
			tex[i - 2] = j;
			dfs(i + 1);
			if (!mark) {
				col[j] = 0;
				ledia[i + j] = 0;
				ridia[7 - i + j] = 0;
				tex[i - 2] = 0;
			}
		}
	}
	return false;
}
int main() {
	int n1, n2;
	cin >> n1 >> n2;
	col[n1 - 1] = col[n2 - 1] = 1;
	ledia[n1-1] = 1, ridia[7 + n1-1] = 1;
	ledia[1 + n2-1] = 1, ridia[7 - 1 + n2-1] = 1;
	dfs(2);
	cout << n1 << " " << n2;
	for (int i = 0; i < 6; i++)cout << " " << tex[i]+1;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值