八皇后问题

Posted darkvalkyrie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了八皇后问题相关的知识,希望对你有一定的参考价值。

1213:八皇后问题


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 5367     通过数: 1856 

【题目描述】

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

【输入】

(无)

【输出】

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

【输入样例】

(无)

【输出样例】

No. 1
1 0 0 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 1 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 
0 0 0 0 0 1 0 0 
0 0 1 0 0 0 0 0 
No. 2
1 0 0 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 0 0 1 0 0 0 0 
0 0 0 0 0 1 0 0 
0 0 0 0 0 0 0 1 
0 1 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
0 0 1 0 0 0 0 0 
...以下省略

例题不怎么详的解:
简介:
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:
在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。
1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。


国际象棋中,皇后可以横斜直三个方向走,步数不受限制,是最强的棋子。
放在本题中考虑,粗略分析,在8*8的棋盘中,要放下八个皇后,每个皇后一定异行异列,才能满足题目要求。

经过以上分析,很明显,每两个皇后之间的位置关系是(用i表示行,j表示列):

ai≠bi,aj≠bj(不同行列),|ai-bi|
≠|aj-bj|,|ai+bi|≠|aj+bj|(不同斜线);

即不同行不同列不同斜线。
好的,基本思路很简单,接下来是算法实现。别看思路简单,其实这是一道经典的难题。



算法分析:
这是一个有点dp的搜索算法。呃。。。回溯算法。
初步思路是设置一个int型一维数组储存皇后的位置;
接下来,就是完成搜索函数的功能了。

逐行放置棋子,同时检查是否符合两棋子之间的条件关系,直到放完8个棋子。
但是我们如何判断两个皇后之间的关系呢?这里是本题的关键。

这里有一种便捷的方法,因为根据算法每个棋子必定异行,那就设置3个数组,表达某处被占地整列,整左斜线,整右斜线
上的格子不得放置下一枚棋子。

为方便起见,我们设置一个关键二维数组vis[3][(此处应大于16,因为最值为i+j=16)].
首先检查当前列,行,斜线上能否放置:
if(vis[0][i]==0&&vis[1][step+i]==0&&vis[2][step-i+8]==0)//注意:vis[2]由于数组会越界,在行列值相减后必须加至大于0;
如果是,放置棋子,并声明棋子所在行,列,斜线全部无法放置棋子:
vis[0][i]=1;
vis[1][i+step]=1;
vis[2][step-i+8]=1;
a[step]=i;

    接下来,搜索下一颗棋子:

dfs(step+1);

   完事了以后要销毁证据/滑稽(回溯):

vis[0][i]=0;
vis[1][i+step]=0;
vis[2][step-i+8]=0;

   肥肠好,到这里搜索部分就基本完成了。

   加入递归边界:

if(step==9)
    {
        tot++;
        for(int i=1;i<=8;i++)
            ans[tot][i]=a[i];//设置传值数组,将所有临时数据传入此数组。
        return;
    }

 大功告成!

   说实话挺简单的,但是我怎么写都是错的,最后还是去看了一眼答案。。。虽说思路一样吧。。。但是为什么我就是错了(蓝瘦)??? 

   没什么需要具体分析的。

   样例代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define N 100
using namespace std;
int ans[N][N],a[N];
int vis[N][N];
int tot;
void dfs(int step)
{
    if(step==8+1)
    {
        tot++;
        for(int i=1;i<=8;i++)
            ans[tot][i]=a[i];
        return;
    }
    for(int i=1;i<=8;i++)
    {
        if(vis[0][i]==0&&vis[1][step+i]==0&&vis[2][step-i+8]==0)
        {
            vis[0][i]=1;
            vis[1][i+step]=1;
            vis[2][step-i+8]=1;
            a[step]=i;
            dfs(step+1);
            vis[0][i]=0;
            vis[1][i+step]=0;
            vis[2][step-i+8]=0;
        }
    }
}
int main()
{
    dfs(1);
    for(int t=1;t<=tot;t++)
    {
        printf("No. %d
",t);
        for(int i=1;i<=8;i++)
        {
            for(int j=1;j<=8;j++)
            {
                if(ans[t][j]==i)
                    cout<<"1 ";
                else
                    cout<<"0 ";
            }
            cout<<endl;
        }
    }
    return 0;
}

2019-02-05 20:59:02

 

以上是关于八皇后问题的主要内容,如果未能解决你的问题,请参考以下文章

八皇后,回溯与递归(Python实现)

基于WPF的八皇后简单应用程序

八皇后问题的遗传算法解法,c语言编写

八皇后问题

八皇后

八皇后问题