八皇后问题简单解法

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?
为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当 n = 1 或 n ≥ 4 时问题有解。
这里写图片描述
仔细分析此题,可以发现:如果我们从第一行开始放置,每行放置一个皇后,将要放置时,我们看有没有与前面的行上放置的皇后在同一列上或者同一对角线上(因为是一行一行的放置下来,所以行必然不会相同)
所以用一个一维数组loc[i] 就可以存放在棋盘上放置的皇后的行列信息:loc[i]=j 表示在棋盘的第i行、第j列上放着一个皇后。
假设i行以前皇后的位置都已经确定,即loc[0~(i-1)]的值已知。
在进行第i行皇后放置时,从该行的第一个位置开始,对所有位置一次进行试探。
令loc[i]=j(即如果放在i行的第j个位置上),与前i-1个皇后不在同列,也没有在对角线上,可以进行下一行皇后的放置。
若冲突了,则右移一位,进行j+1位置的试探。
判断是否与前面的皇后在同列以及是否对角线也比较容易。
同列? 第1行到i-1行是否存在loc[i]=loc[x]?
对角线? i-x=abs(loc[i]-loc[x])?

【代码如下】

#include<iostream>
#include<cmath> 
#define N 8//棋盘行列数,即皇后个数。 
using namespace std;
int sum=0;//总的可能数。

bool check(int loc[],int x)//检查当前这种放置,判断可以这样放是否可行。 
{
    for(int i=0;i<x;i++)
    {
        //loc[i]==loc[x]进行列判断。
        //abs(x-i)==abs(loc[x]-loc[i]) 是否在对角线上。 
        if(loc[i]==loc[x]||abs(x-i)==abs(loc[x]-loc[i]))
        return false;
    }   
    return true;
} 


void show(int loc[])//显示放置皇后的棋盘 
{
    sum++;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            if(loc[i]==j)
            cout<<" A ";
            else
            cout<<" - ";
        }
        cout<<endl; 
    }   
}


void Queen(int loc[],int x)//loc[]存储已经放置的皇后坐标,x表示行。 
{
    if(x==N)//全部放完,已放到了最后一行。输出 
    {
        show(loc);
        cout<<endl<<endl;
        return;
    }
    for(int i=0;i<N;i++)
    {
        loc[x]=i;//第x行,从0个位置到N-1 循环判断是否可以放置, 
        if(check(loc,x))
        {
            Queen(loc,x+1);//可以放,继续放下一行。 
        } 

        //不能放则右移一位,试探这一行的下一个位置; 
    }
 } 


 int main()
 {
    int loc[N];//存储第i行皇后的位置
    Queen(loc,0);//从0行开始放置。 
    cout<<sum<<endl;  
 }
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Casionx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值