题解之八皇后问题

本文介绍了八皇后问题的背景、规则以及如何使用回溯算法和递归实现,详细解释了如何通过判断行、列和斜线来避免皇后互相攻击,给出了C++代码示例。
摘要由CSDN通过智能技术生成

一,题目描述

描述

在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。

输入

无输入。

输出

按给定顺序和格式输出所有八皇后问题的解。

二,思路分析

不得不说这道题是真有难度。首先没玩过国际象棋的人连规则都不懂 ,谈何做题?!

所以,让我们康康百度怎么说:

八皇后问题(英文:Eight queens),是由国际象棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。

问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。计算机发明后,有多种计算机语言可以编程解决此问题。

(好的谢谢百度登场) 

 其实这道题是一个回溯的算法,但本人拿函数加递归做的。

题目说不让在同一行或同一列,那我们要么一行一行的找看列,要么一列一列的找看行。

但斜边怎么办?

我们直接上结论:

从左上到右下,行与列之差相等;从右上到左下,行与列之和相等。

大家可以自己根据国际象棋的棋盘去推导,很容易推导出来。

我们定义三个数组,用来标记行,左上到右下和右下到左上三种情况,用来判断是否能落子。

三,递归实现

#include<iostream>
using namespace std;
int o[105][105],l[105],p[105],x[105],sum=1;  //所需数组变量全部定义成全局 
void fun(int n)  //直接输出用void 
{
    int i,j,k;  //只在函数中使用的变量 
    if(n>8)  //程序的边界(递归出口) 
    {
        
        //开始输出 
        cout<<"No.  "<<sum<<endl;
        sum=sum+1; //记录方法数 
        //二维数组的输出 
        for(j=1;j<=8;j++)  
        {
            for(k=1;k<=8;k++)
            {
                cout<<o[j][k]<<"  ";
            }
            cout<<endl;
        }
        return;  /返回上一层 
    }
    for(i=1;i<=8;i++)  //一列一列判断行 
    {
        //标记 :l[n]==0是当前行没有被用过,p[n+i]==0是当前从右上到左下的斜边是否被使用过,x[i-n+8]==0当前从左上到右下的斜边是否被使用过
        if(l[n]==0&&p[n+i]==0&&x[i-n+8]==0) //加8是因为可能出现负数 
        {
            l[i]=1;  //使用后的标记 
            p[n+i]=1;
            x[i-n+8]=1;
            o[i][n]=1;
            fun(n+1);  //本层已找到进入下一层 
            //还原现场 
            o[i][n]=0;  
            l[i]=0;
            p[n+i]=0;
            x[i-n+8]=0;
        }
    }
    return;  //回到上一层 
}
int main()
{
    fun(1);  //主函数中调用 
}

#include<iostream>
using namespace std;
int o[105][105],l[105],p[105],x[105],sum=1; 
void fun(int n) 
{
	int i,j,k; 
	if(n>8) 
	{
		cout<<"No.  "<<sum<<endl;
		sum=sum+1; 
		for(j=1;j<=8;j++)
		{
			for(k=1;k<=8;k++)
			{
				cout<<o[j][k]<<"  ";
			}
			cout<<endl;
		}
		return; 
	}
	for(i=1;i<=8;i++) 
	{
		if(l[n]==0&&p[n+i]==0&&x[i-n+8]==0)  
		{
			l[i]=1; 
			p[n+i]=1;
			x[i-n+8]=1;
			o[i][n]=1;
			fun(n+1); 
			o[i][n]=0;
			l[i]=0;
			p[n+i]=0;
			x[i-n+8]=0;
		}
	}
	return; 
}
int main()
{
	fun(1); 
}

(92种情况,我就不展示输出结果了,额有点多) 

结束!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值