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

题目:在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;
}

猜你喜欢

转载自blog.csdn.net/LUCAS004/article/details/107434431
今日推荐