八皇后问题题解

在国际象棋棋盘上:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8,其中bi为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。
给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。

输入格式:

输入共n+1行。第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)

输出格式:

输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。

输入样例:

2
1
92 

输出样例:

15863724
84136275

 题目分析:

8*8个方格中,每一颗棋子同一行同一列同一斜线上不存在棋子,但一行一行循环判断过于复杂,时间复杂度也高,所以我们可以采用列举出1-8所有的全排列,再筛选的暴力解法

void f(int a[],int m,int e[]){
    int i,t;
    static int const_=0;    
    int bool_=1;            //设bool_来记录是否上一个判断通过
    static int count=0;       
    int rol[8];
    if(m==7){
        for(int i=0;i<8;i++){        //判断斜线上是否有棋子
            for(int j=i+1;j<8;j++){
                if(a[i]+i==a[j]+j || a[i]-i==a[j]-j){
                    bool_=0;        //若有bool_==0
                }
            }
        }

定义一个判断函数,为什么判断条件是m==7一会儿再解释,第一个循环判断斜线上是否已经有棋子,a[i]存储的是每一行存在的棋子的列坐标,在同一斜线上,横坐标纵坐标和相等,所以可以判断是否再同一斜线上

if(bool_==1){        //判断第一个判断条件是否通过
            for(int i=0;i<8;i++){
                e[count]+=a[i];
                e[count]*=10;
            }e[count]/=10;
             count++;
       }

由于题目让我们从小到大比较串后输出,这里是将满足条件的全排列变成一个八位数存储进e数组以便于后面从小到大筛选,以及选择要输出的串。

for(i=m;i<8;i++){
        t=a[m];a[m]=a[i];a[i]=t;
        f(a,m+1,e);
        t=a[m];a[m]=a[i];a[i]=t;
        }

以上是利用函数递归进行全排列,m每进行一次排列值就会加一,当m=7时代表全排列结束,得到一个排列后的数,然后我们就可以进行前面所提到的判断全排列是否符合八皇后标准。

int main()
{
    int e[92]={0};
    int a[8]={1,2,3,4,5,6,7,8};
    int n,m=0,t;
    int b[92],c[92];
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&b[i]);
    }
    f(a,m,e);        //调用八皇后函数
    for(int i=0;i<91;i++){            //对八皇后数列进行排序
        for(int j=0;j<91-i;j++){
            if(e[j]>e[j+1]){
                t=e[j+1];e[j+1]=e[j];e[j]=t;
            }
        }
    }
    for(int i=0;i<n;i++){
        t=b[i]-1;            //根据输入的值来输出所需要的数列
        printf("%d",e[t]);
        printf("\n");
    }
    return 0;
}

这里是主函数,比起上面的函数较为简单,这里就不过多赘述。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void f(int a[],int m,int e[]);
void f(int a[],int m,int e[]){
    int i,t;
    static int const_=0;
    int bool_=1;
    static int count=0;
    int rol[8];
    if(m==7){
        for(int i=0;i<8;i++){
            for(int j=i+1;j<8;j++){
                if(a[i]+i==a[j]+j || a[i]-i==a[j]-j){
                    bool_=0;
                }
            }
        }
        if(bool_==1){
            for(int i=0;i<8;i++){
                e[count]+=a[i];
                e[count]*=10;
            }e[count]/=10;
             count++;
       }
   }

    for(i=m;i<8;i++){
        t=a[m];a[m]=a[i];a[i]=t;
        f(a,m+1,e);
        t=a[m];a[m]=a[i];a[i]=t;
        }
    }


int main()
{
    int e[92]={0};
    int a[8]={1,2,3,4,5,6,7,8};
    int n,m=0,t;
    int b[92],c[92];
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&b[i]);
    }
    f(a,m,e);
    for(int i=0;i<91;i++){
        for(int j=0;j<91-i;j++){
            if(e[j]>e[j+1]){
                t=e[j+1];e[j+1]=e[j];e[j]=t;
            }
        }
    }
    for(int i=0;i<n;i++){
        t=b[i]-1;
        printf("%d",e[t]);
        printf("\n");
    }
    return 0;
}

这里是完整的代码,仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值