八皇后(c语言)

代码+解释说明+心得 (按顺序来的

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

#include <stdbool.h>

int longitudinal[100];
int queen[100][100];

bool place (int);     /*找到皇后合适的列位置*/
void Queen (int);     /*找到所有皇后合适的位置,并矩阵输出*/

int main(int argc, char *argv[]) {

       int num;
   
    printf ("Please input the number of Queens:\n");
       scanf ("%d", &num);
   
    Queen (num);

    return EXIT_SUCCESS;
}

/*检索皇后 Q 放置在 longitudinal[Q] 列是否发生冲突*/
bool place (int Q) {         
    int i;
    
    for (i = 1; i < Q; i++)
            if(longitudinal[Q] == longitudinal[i] || abs(Q-i) == abs(longitudinal[Q] -longitudinal[i]))
                    return true;

        return false;

}

/*回溯,找出所有皇后 Q 合适的位置,并矩阵输出*/
void Queen(int num) {

        int i, j;
        int Q = 1;
        int ways = 0;

       memset (longitudinal, 0, sizeof(int)*num);      /*初始化数组 Q*/

        while(Q >= 1) {

            longitudinal[Q] = longitudinal[Q] + 1;   /*在下一列放置第 Q 个皇后*/

            while(longitudinal[Q] <= num && (place(Q))) {
 
                longitudinal[Q] = longitudinal[Q]+1; /*检索下一列*/
             }

            if(longitudinal[Q] <= num && (Q == num)) {    /*得到一个,则输出一个*/
            
                ways++;
                printf ("\n%d\n", ways);

                memset (queen, 0, sizeof(queen));    /*初始化数组queen*/

                for(i = 1; i <= num; i++) {          /*若时皇后,则为1,否则,为0*/
                    
                    for (j = 1; j <= num; j++) {
                        
                        if (longitudinal[i] == j) {
                      
                            queen[i][j] = 1;

                        }

                   }

                }

                for (i = 1; i <= num; i++) {
        
                    for (j = 1; j <= num; j++)
                      printf ("%d ", queen[i][j]);

                    printf ("\n");
        
                }
              
        }
        
    else if (longitudinal[Q] <= num && Q < num) {
            
        Q = Q + 1;         /*放置下一个皇后Q+1*/

    }
        
    else {
            
                longitudinal[Q] = 0;     /*本个皇后位置初始为0,回到上个皇后,向后重新选位(回溯)*/
                Q = Q - 1;

        }

    }

}

解释说明:此代码先用一维数组Q找到皇后的合适位置,以二维数组longitudinal形式输出。先用一维数组的原因如下:数组Q的下标相当于时皇后的横坐标,而数组Q对应的值代表列,如:Q[1]=2,则为把第一个皇后放在第一行,第二列;如果用一维数组Q来找到皇后位置的话,在函数place中,判断是否在同行,列,对角线上时,无需判断是否同行。采用二维数组longitudinal的形式输出,更加形象直观的显示出所有皇后位置的摆放。

小编心得:在使用memset函数初始化时,注意参数的摆放位置,在初始化二维数组时,注意,要么用一重循环部分初始化,要么,不用循环,全部初始化,就像小编一样啦。当时,小编就米有用循环,结果直接初始化,结果,输出不对,等到明白原因时,顿时觉得,原来自己当时撒比的一下,就米有想到呢。下次要注意啦~ 还有就是,要么从头到尾用 i=1;i<=n;i++,要么,就从头到尾使用i=0;i<n;i++,防止越界或者别的。

### 将全排列算法改写为解决皇后问题的C语言实现 皇后问题是经典的回溯算法应用之一,其目标是在8×8棋盘上放置皇后,使得任意两个皇后都不能互相攻击。通过修改全排列算法的核心逻辑,可以将其转化为适用于皇后问题的形式。 以下是基于全排列算法的思想改写的皇后问题解决方案: #### 改写思路 1. **状态表示**:用数组 `col[]` 表示每一行皇后的列位置。 2. **约束条件**:在放置第 k 个皇后时,需满足以下条件: - 不在同一列; - 不在同一条斜线上(左上至右下或右上至左下)。 3. **递归终止条件**:当成功放置了 8 个皇后时结束递归并记录解法。 4. **回溯机制**:如果某一行无法找到合适的位置,则退回至上一层重新尝试其他可能的选择。 #### 实现代码 ```c #include <stdio.h> #define N 8 void printSolution(int col[]) { static int solutionCount = 0; solutionCount++; printf("Solution %d:\n", solutionCount); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (j == col[i]) { printf("Q "); } else { printf(". "); } } printf("\n"); } printf("\n"); } bool isSafe(int row, int column, int col[]) { for (int i = 0; i < row; i++) { if (col[i] == column || abs(col[i] - column) == abs(i - row)) { return false; } } return true; } void solveNQueensUtil(int row, int col[], bool* foundSolutions) { if (row == N) { printSolution(col); *foundSolutions = true; return; } for (int c = 0; c < N; c++) { if (isSafe(row, c, col)) { col[row] = c; solveNQueensUtil(row + 1, col, foundSolutions); } } } void solveNQueens() { int col[N]; bool foundSolutions = false; for (int i = 0; i < N; i++) { col[0] = i; solveNQueensUtil(1, col, &foundSolutions); } } int main() { solveNQueens(); return 0; } ``` #### 关键点解析 1. **安全性检测函数** `isSafe()` 判断当前位置 `(row, column)` 是否安全[^1]。 2. **递归调用** `solveNQueensUtil()` 负责逐层放置皇后,并在遇到合法解时打印结果。 3. **全局变量替代** 使用静态变量 `solutionCount` 来统计总方案数[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值