编程训练——八皇后升级版:N皇后问题

【八皇后问题和算法介绍】
简书上看到一篇极好的文章:点这跳转

算法简单易懂,只写八皇后太没意思,干脆让用户指定皇后数量,写个升级版的“N皇后”问题。

【运行情况概览】
输入一个正数n(不超过20),输出对应n皇后问题的解:

1
(1)
1皇后问题有1组解,以上呈现各行皇后分别放在第几列
2
2皇后问题无解
3
3皇后问题无解
4
(2 4 1 3)
(3 1 4 2)
4皇后问题有2组解,以上呈现各行皇后分别放在第几列
5
(1 3 5 2 4)
(1 4 2 5 3)
(2 4 1 3 5)
(2 5 3 1 4)
(3 1 4 2 5)
(3 5 2 4 1)
(4 1 3 5 2)
(4 2 5 3 1)
(5 2 4 1 3)
(5 3 1 4 2)
5皇后问题有10组解,以上呈现各行皇后分别放在第几列
6
(2 4 6 1 3 5)
(3 6 2 5 1 4)
(4 1 5 2 6 3)
(5 3 1 6 4 2)
6皇后问题有4组解,以上呈现各行皇后分别放在第几列

【示例代码】

#include<stdio.h>

//#define MAXSIZE 20;
//int a[MAXSIZE][MAXSIZE];    //这种定义方式在Xcode中会报蜜汁错误:Unexpected ';' before ']'

int a[20][20];
int n;
int total;

int FindIndexOfOne(int row){	//找到第row行皇后的列数(从0开始计数)
    for(int col=0;col<n;col++){
        if(a[row][col]==1)return col;
    }
    return -1;
}

void PrintAns(){	//打印各行皇后的列数(从1开始计数)
    int row;
    printf("(");
    for(row=0;row<n-1;row++){
        printf("%d ",FindIndexOfOne(row)+1);
    }
    printf("%d)\n",FindIndexOfOne(row)+1);
}

int NoAttack(int row,int col){	//检测row行col列位置放置的皇后是否不会被攻击
    for(int i=0-n;i<n;i++){
        if(row+i>=0&&row+i<n&&col+i>=0&&col+i<n&&a[row+i][col+i]==1)return 0;
        if(row+i>=0&&row+i<n&&a[row+i][col]==1)return 0;
        if(row+i>=0&&row+i<n&&col-i>=0&&col-i<n&&a[row+i][col-i]==1)return 0;
        if(col-i>=0&&col-i<n&&a[row][col-i]==1)return 0;
    }
    return 1;
}

void FindQueen(int row){	//算法核心
    if(row>=n){		//递归边界,此时已经求出一种解
        PrintAns();
        total++;
    }
    else{
        for(int col=0;col<n;col++){
            if(NoAttack(row,col)==1){
                a[row][col]=1;
                FindQueen(row+1);
                a[row][col]=0;  //比较难懂的一步,作用是回溯时清楚这个位置上的皇后,不然棋盘最终会被摆上超过n个皇后。
                                //因为找齐n个皇后就直接输出结果,所以清除也不会影响结果
            }
        }
    }
}

int main(){
    total=0;
    while(scanf("%d",&n)==1){
        FindQueen(0);   // 误将0写成n,FindQueen的参数是一个整数,意思是从第几行开始找皇后
        if(total!=0){
            printf("%d皇后问题有%d组解,以上呈现各行皇后分别放在第几列\n",n,total);
        }
        else printf("%d皇后问题无解\n",n);
        total=0;
    }
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值