经典题型之回溯算法——八皇后问题

题目:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法,并把每一种结果打印出来。


#include <stdio.h>

//判断能不能在cnt行第col列摆放一个皇后  能返回1 不能返回0
int judge(int queens[],size_t n,size_t row,size_t col){
    int i = 0;
    //遍历当前皇后的位置有没有和前面皇后的位置相互威胁
    for(i=0;i<row;i++){
    	//如果在同一列同一斜线有其他的皇后,则构成威胁,返回0
        if(queens[i]==col || abs(queens[i]-col)==abs(i-row)){
            return 0;
        }   
    }   
    return 1;//当前位置无威胁,返回1
}

// 输出当前摆法的8个皇后的位置
void show(int queens[],size_t n){   
    int i = 0;
    for(i=0;i<n;i++){
        printf("%d ",queens[i]);
    }   
    printf("\n");
}

//回溯算法
int putqueens(int queens[],size_t n){ 
    int col = 0; //记录在摆放第几个皇后  从0开始
    int row = 0; //皇后摆放所在的列
    int sum = 0; //记录摆法有多少种
    while(1){
    	//当第一行的皇后到达第八列并且第二行的皇后到达倒数第二列的时候结束循环(在同一斜线上)
        if(queens[0]==n-1 && row==1 && col>=n-2){
            break;
        }
        //在row行col列摆放皇后
        if(judge(queens,n,row,col)==1){//判断能不能摆放皇后
            queens[row] = col;//摆放了一个皇后
            ++row;//去到下一行摆放皇后
            col = 0;//从第0列开始摆放
            if(row>=n){//已经摆放好了全部的皇后
                sum++;//摆法+1
                show(queens,n);//打印当前摆法的八个皇后的位置
                --row;//回退到第八个皇后
                col = queens[row] + 1;//将第八个皇后的位置往后移动一列
                while(col>=n){//到棋盘外
                    --row;//移动上一个皇后
                    col = queens[row] + 1;//将上一个皇后的位置往后移动一列
                }
            }
        }else{//第col列不能摆放 
            ++col;//下一列试一下
            while(col>=n){//棋盘外
                --row;//要移动上一个皇后了
                col = queens[row] + 1;//上一个皇后的位置往后移动一列,如果到棋盘外,则再次循环,移动上一个皇后
            }
        }
    }
    return sum;
}

int main(){
	//每一行都有一个皇后 只需要记录第一行中的列位置即可
    int queens[8] = {0};
    int sum = putqueens(queens,8);
    printf("%d\n",sum);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值