0
点赞
收藏
分享

微信扫一扫

C++/C (n皇后问题 回溯法)完整版

八卦城的酒 2022-03-12 阅读 89
c++

题目描述

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

国际象棋中,同一行、同一列、同一斜线上的皇后可以相互攻击

求n皇后问题的摆放方案数量 。 

输入

正整数n (4 <= n <= 10)

输出

n皇后问题的摆放方案数量

样例输入

8

样例输出

92

                  (选自HUSTOJ网站 ,网址115.28.211.117 有兴趣可以注册一个号,海量题目等你来刷)

   道题是由国际象棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。首先要先明确大致思路:即先创造一个涵数用来判断这个位置可不可以下(因国际象棋中,同一行、同一列、同一斜线上的皇后可以相互攻击),再void一个函数来下子和计数。

     先创造一个Check涵数用来判断这个位置可不可以下

int Check(int line,int list){
    //遍历该行之前的所有行
    for (int index=0; index<line; index++) {
        //挨个取出前面行中皇后所在位置的列坐标
        int data=Queenes[index];
        //如果在同一列,该位置不能放
        if (list==data) {
            return 0;
        }
        //如果当前位置的斜上方有皇后,在一条斜线上,也不行
        if ((index+data)==(line+list)) {
            return 0;
        }
        //如果当前位置的斜下方有皇后,在一条斜线上,也不行
        if ((index-data)==(line-list)) {
            return 0;
        }
    }
    //如果以上情况都不是,当前位置就可以放皇后
    return 1;
}

    定义一个函数下子

void print()
{
    for (int line = 0; line < n; line++)
    {
        int list;
        for (list = 0; list < Queenes[line]; list++)
           
        
        for (list = Queenes[line] + 1; list < n; list++){
            
        }
        
    }
    
}

最后进行回溯并计数

void eight_queen(int line){
    //在数组中为0-n-1列
    for (int list=0; list<n; list++) {
        //对于固定的行列,检查是否和之前的皇后位置冲突
        if (Check(line, list)) {
            //不冲突,以行为下标的数组位置记录列数
            Queenes[line]=list;
            //如果最后一样也不冲突,证明为一个正确的摆法
            if (line==n-1) {
                //统计摆法的Counts加1
                Counts++;
                //输出这个摆法
                print();
                //每次成功,都要将数组重归为0
                Queenes[line]=0;
                return;
            }
            //继续判断下一样皇后的摆法,递归
            eight_queen(line+1);
            //不管成功失败,该位置都要重新归0,以便重复使用。
            Queenes[line]=0;
        }
    }
}

 整体代码如下:

#include<bits/stdc++.h>  
//此为万能头文件,但定义的变量名不能为max或min
using namespace std;
int Queenes[8]={0},Counts=0,n;
int Check(int line,int list){
    //遍历该行之前的所有行
    for (int index=0; index<line; index++) {
        //挨个取出前面行中皇后所在位置的列坐标
        int data=Queenes[index];
        //如果在同一列,该位置不能放
        if (list==data) {
            return 0;
        }
        //如果当前位置的斜上方有皇后,在一条斜线上,也不行
        if ((index+data)==(line+list)) {
            return 0;
        }
        //如果当前位置的斜下方有皇后,在一条斜线上,也不行
        if ((index-data)==(line-list)) {
            return 0;
        }
    }
    //如果以上情况都不是,当前位置就可以放皇后
    return 1;
}
//输出语句
void print()
{
    for (int line = 0; line < n; line++)
    {
        int list;
        for (list = 0; list < Queenes[line]; list++)
           
        
        for (list = Queenes[line] + 1; list < n; list++){
            
        }
        
    }
    
}
void eight_queen(int line){
    //在数组中为0-n-1列
    for (int list=0; list<n; list++) {
        //对于固定的行列,检查是否和之前的皇后位置冲突
        if (Check(line, list)) {
            //不冲突,以行为下标的数组位置记录列数
            Queenes[line]=list;
            //如果最后一样也不冲突,证明为一个正确的摆法
            if (line==n-1) {
                //统计摆法的Counts加1
                Counts++;
                //输出这个摆法
                print();
                //每次成功,都要将数组重归为0
                Queenes[line]=0;
                return;
            }
            //继续判断下一样皇后的摆法,递归
            eight_queen(line+1);
            //不管成功失败,该位置都要重新归0,以便重复使用。
            Queenes[line]=0;
        }
    }
}
int main() {
    //调用回溯函数,参数0表示从棋盘的第一行开始判断
    scanf("%d",&n);
    eight_queen(0);
    printf("%d",Counts);
    return 0;
}

                                                         希望对大家有帮助,求关注,收藏!

举报

相关推荐

0 条评论