• 8皇后问题


    描述

    在8x8的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。

    问:

    1. 有多少种解法?
    2. 这些解法分别是什么?

    思路

    枚举所有皇后的位置,直到8个皇后都放完或没有皇后可放时输出结果。

    为了方便编程,我们先输出每一个解法,接着输出一共有多少种解法。

    代码

    /*
     * 阅读代码顺序:从下至上
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define MARK(r, c) do { 
        if (newBoard[r][c] == AVAILABLE) { 
            newBoard[r][c] = UNSAFE; 
        } 
    } while (0)
    
    #define CHECK_AND_MARK(r, c) do { 
        if (0 <= r && r < 8 && 0 <= c && c < 8 && 
            newBoard[r][c] == AVAILABLE) { 
                newBoard[r][c] = UNSAFE; 
        } 
    } while (0)
    
    /*
     * 3: queens函数的辅助宏
     */
    
    /*
     * 储存某一时刻的棋盘信息
     */
    enum {
        QUEEN     = 'X', // 放了皇后
        AVAILABLE = '_', // 没放皇后但可以放
        UNSAFE    = '.'  // 没放皇后且不能放
    };
    typedef char Chessboard[8][8];
    
    void queens(Chessboard board, unsigned n, unsigned *total) {
    /*     在棋盘board上,从第n个皇后枚举到第8个皇后,将解法总和加到total上
     *     如果遇到解法,则输出
     */
        if (n == 9) { // 输出
            int r, c;
            for (r = 0; r < 8; ++r) {
                for (c = 0; c < 8; ++c) {
                    printf("%s%c%s",
                           (c == 0) ? "|" : "",
                           board[r][c],
                           (c == 7) ? "|
    " : "|");
                }
            }
            printf("
    ");        
            
            ++*total;
        } else {
            int r, c;
    
            for (r = n - 1; r < 8; ++r) {
                for (c = 0; c < 8; ++c) {
                    if (board[r][c] != AVAILABLE) continue;
                    
                    Chessboard newBoard;
                    memcpy(newBoard, board, sizeof(Chessboard));
                    newBoard[r][c] = QUEEN;
    
                    int rr, cc, i;
                    for (cc = 0; cc < 8; ++cc) { // 行
                        MARK(r, cc); // 标上UNSAFE
                    }
                    for (rr = 0; rr < 8; ++rr) { // 列
                        MARK(rr, c);
                    }
                    for (i = 1; i < 8; ++i) { // 对角线
                        // 若点(x,y)与点(x',y')处于同一对角线,则
                        // |x'-x| = |y'-y|
                        CHECK_AND_MARK(r + i, c + i); // 假如坐标合法,标UNSAFE
                        CHECK_AND_MARK(r + i, c - i);
                        CHECK_AND_MARK(r - i, c + i);
                        CHECK_AND_MARK(r - i, c - i);
                    }
    
                    queens(newBoard, n + 1, total);
                }
            }
        }
    }
    
    /*
     * 2: queens函数及Chessboard类型
     */
    
    int main(int argc, char **argv) {
        Chessboard board;
        memset(board, AVAILABLE, sizeof(Chessboard));
        
        unsigned total = 0;
        
        queens(board, 1, &total);
        
        printf("Total: %d
    ", total);
    
        exit(0);
    }
    
    /*
     * 1: Main
     */
    
  • 相关阅读:
    [转]Linq to SQL Like Operator
    [转]updatepanel中使用alert弹出框方法
    [转]MSDN 在客户端脚本中为 UpdateProgress 控件编程
    [转].NET Framework 3.5 SP1安装时下载文件问题及精简方法
    Vista系统下IIS安装 用以创建支持vs2008开发的网站
    asp.net 文本框输入时的自动完成
    [转]Raising An Event From CheckBox In A GridView (GridView中模板表的CheckBox的后台事件处理)
    I have my family
    拉了网线 多了机会
    【转】DataGridViewComboBoxColumn的使用
  • 原文地址:https://www.cnblogs.com/jt2001/p/5179487.html
Copyright © 2020-2023  润新知