一、问题描述

在n行n列的棋谱上,放n个棋子,保证:这n个棋子任意两个不在同一行,不在同一列,并且也不在对角线上,这样的摆法有多少种?

二、解题思路

使用递归回溯解题。
定义一个一维数组,下标存放列值存放行
n表示为n行n列的棋谱,n个棋子
首先从第一列开始放,然后再放第二列,放第二列时需与第一列时比较,是否在同一行或者同一列或者对角线上。如果是,重新摆放第二列的位置;如果不是,继续下一列。摆放第k列时,需与前k-1列相比较是否符合规则,不符合重新摆放第k列的位置,若第k列所有行摆放都不符合规则,则回溯到第k-1列进行与前k-2列进行比较;符合的话进行第k+1列。当将n列全部都放完之后(说明这n列摆放符合规则),回溯到第n列重新摆放,如果不符合规则继续回溯到第n-1列……依次类推直到所有情况都检测完为止

三、代码实现

#include <iostream>
#include <cmath>

using namespace std;

const int MAXSIZE=20;
int *t=new int[MAXSIZE];//n行n列
int sum=0;//解数

bool place(int i){
    if(i<=1){
        //当为第一列时,前边没有列,无需比较
        return true;
    }
    for(int s=1; s<i; s++)
        //第i列与第s列(一定在第i列之前)在对角线或者在同一行时
        if(abs(t[i]-t[s])==i-s||t[i]==t[s])
            return false;
    return true;
}

void backTrack(int i,int n){
    if(i>n){
        //n行全部试完,解数+1 ,回溯
        cout<<"(";
        for(int k=1;k<=n;k++){
            if(k==n){
                cout<<t[k]<<")"<<endl;
                break;
            }
            cout<<t[k]<<",";
        }
        sum++;
        return;
    }
    for(int j=1; j<=n; j++){
        //第i列 第j行
        t[i]=j;
        if(place(i))
         	//
            backTrack(i+1,n);
    }
}

int main(){
    cout<<"几皇后?"<<endl;
    int n;
    cin>>n;
    backTrack(1,n);
    cout<<sum;
    return 0;
}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐