📜  N皇后问题的C程序|回溯3(1)

📅  最后修改于: 2023-12-03 15:33:16.236000             🧑  作者: Mango

N皇后问题的C程序|回溯3

简介

这是一份使用回溯算法解决N皇后问题的C程序,N皇后问题是指在N×N的棋盘上摆放N个皇后,使得皇后之间互相不能攻击,即任意两个皇后不得处于同一行、同一列或同一斜线上。

本程序使用回溯算法求解,即从第一行开始依次尝试在每列放置皇后,并检查是否合法,若合法则进入下一行,若所有列都无法放置则回退到上一行重新尝试。通过逐层深入、回溯试错的方式求解问题。

程序
#include <stdio.h>
#define N 8

int Queens[N] = {0};    // 皇后在每列的位置
int Tot = 0;    // 解的个数

// 判断在第row行第col列是否可以摆放皇后
int Valid(int row, int col){
    for(int i=0; i<row; i++){
        if(Queens[i]==col || abs(Queens[i]-col)==abs(i-row)){
            return 0;
        }
    }
    return 1;
}

// 对第row行进行回溯
void Search(int row){
    if(row==N){    // 找到一组解
        Tot++;
        printf("Solution %d:\n", Tot);
        for(int i=0; i<N; i++){
            for(int j=0; j<N; j++){
                if(Queens[i]==j){
                    printf(" Q");
                }else{
                    printf(" +");
                }
            }
            printf("\n");
        }
        printf("\n");
        return;
    }
    for(int i=0; i<N; i++){    // 尝试在每列放置皇后
        if(Valid(row, i)){
            Queens[row] = i;
            Search(row+1);    // 尝试下一行
        }
    }
}

int main(){
    Search(0);
    printf("Total solutions: %d\n", Tot);
    return 0;
}
代码片段解释
宏定义
#define N 8

定义了N皇后问题的规模,这里默认为8x8。

变量定义和初始化
int Queens[N] = {0};    // 皇后在每列的位置
int Tot = 0;    // 解的个数

Queens数组是长度为N的数组,表示拜访了各行的皇后摆放在每列的位置。Tot表示找到的解的个数,初值为0。

判断是否可行的函数
// 判断在第row行第col列是否可以摆放皇后
int Valid(int row, int col){
    for(int i=0; i<row; i++){
        if(Queens[i]==col || abs(Queens[i]-col)==abs(i-row)){
            return 0;
        }
    }
    return 1;
}

Valid函数返回值为整数,表示传入的row,col是否可行。其中,row是当前要判断的行数,col是当前行尝试放置皇后的列数,即(row,col)。

函数内部通过循环遍历各行所放置皇后的位置,检查是否与新的皇后位置在同一列或同一斜线上。若出现冲突则返回0,否则返回1。

回溯函数
// 对第row行进行回溯
void Search(int row){
    if(row==N){    // 找到一组解
        Tot++;
        printf("Solution %d:\n", Tot);
        for(int i=0; i<N; i++){
            for(int j=0; j<N; j++){
                if(Queens[i]==j){
                    printf(" Q");
                }else{
                    printf(" +");
                }
            }
            printf("\n");
        }
        printf("\n");
        return;
    }
    for(int i=0; i<N; i++){    // 尝试在每列放置皇后
        if(Valid(row, i)){
            Queens[row] = i;    // 第row行放在第i列
            Search(row+1);    // 尝试下一行
        }
    }
}

Search函数参数row表示当前的行数,函数中先检查当前是不是最后一行,如果是则表示找到一组解,将解的个数加1,并输出该解的皇后位置。

否则,程序依次尝试在每列放置皇后,每次调用Valid函数来检查当前位置是否可行。如果当前位置可行,则将皇后在当前行中的位置更新为Queens[row]=i,调用自己递归到下一层,即Search(row+1)

主函数
int main(){
    Search(0);
    printf("Total solutions: %d\n", Tot);
    return 0;
}

程序的主函数中仅调用了回溯函数Search,并在匹配完成后输出总解数。

总结

本程序使用了回溯算法求解N皇后问题,同时输出了每组解的位置。可以通过改变程序中的N值来寻找不同规模的N皇后问题的解。