欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

八皇后问题

程序员文章站 2022-03-07 15:11:42
...

八皇后问题

是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

以4皇后为例,如图所示,在图(a)中,第1行第1列上放置一个皇后,图(b)中确定第2行的可能放法,在尝试第1列、第2列由于相互攻击而放弃之后,确定在第3列放置可以继续,在图(c)中继续对第3行进行考察,发现将所有4列都尝试过了,也没有办法将皇后安排一个合适的位置,对第4行做任何的尝试都没有意义,这时产生回溯,结果是在图(d)中将第2行的皇后安排到第4列,然后第3行的暂时可以放在第2列,在图(e)中试着确定第4行的皇后,却发现无解再次回溯,只能够如图8.22(f)所示将第1行的皇后放到第2列,再经图(g)、(f)之后找到4皇后问题的一个解,那就是图(g)的(2, 4, 1, 3)。
八皇后问题

搞清楚用回溯法求解的过程后,将关注什么样的解才是可行的?需要描述出任何两个皇后可以“互相攻击”这样的条件:
  (1)有两个皇后处在同一行
  (2)有两个皇后处在同一列
  (3)有两个皇后处在同一斜线
所以我们只需要判断不满足上述三个条件即可!
八皇后问题
假设此时位置处于X,只要遍历(x-1,y-1)、(x-1,y)、(x-1,y+1)三个方向,只要能在等于 ” * ” 前找到等于 “ # ”,就说明此方向没有皇后。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#define N 8
char board[N + 2][N + 2];

typedef struct Pos
{
    int xos;
    int yos;
}pos_t;
pos_t pos[3] = {    //定义1个结构体,表示移动的位数(x-1,y-1)\(x-1,y)\(x-1,y+1)
    { -1, -1 },
    { -1, 0 }, 
    { -1, 1 } 
};

void Initboard()//初始化棋盘
{
    int i, j = 0;
    for (i = 1; i <= N; i++)
    {
        for (j = 1; j <= N; j++)
        {
            board[i][j] = ' ';
        }
    }
    for (i = 0; i <= N+1; i++)
    {
        board[0][i] = '#';
        board[i][N + 1] = '#';
        board[N + 1][i] = '#';
        board[i][0] = '#';
    }
}

void display()//显示棋盘
{
    int i, j = 0;
    for (i = 0; i < N + 2; i++)
    {
        printf("------------------------------\n");
        for (j = 0; j < N + 2; j++)
        {
            printf("%2c|", board[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

int check(int i, int j)//检查当前行是否可以放。返回0说明不能放;1能放
{
    int k = 0;
    int ret = 1;
    for (k = 0; k < 3; k++)
    {
        int nx = i;
        int ny = j;
        while (ret && (board[nx][ny] != '#'))
        {
            if (board[nx][ny] == '*')
                ret = 0;
            nx += pos[k].xos;
            ny += pos[k].yos;
        }
    }
    return ret;
}

void Find(int line)
{
    static int count = 0;
    if (line > N)
    {
        count++;
        printf("共有%d种情况\n", count);
        display();
    }
    else
    {
        int j = 0;
        for (j = 1; j <= N; j++)
        {
            if (check(line,j))
            {
                board[line][j] = '*';
                Find(line + 1);
                board[line][j] = ' ';// 下一行不能放,说明当前行的当前位置不合适 
            }
        }
    }
}

int main()
{
    Initboard();
    Find(1);
    system("pause");
    return 0;
}

八皇后问题

回溯法

回溯法是一种通用的搜索算法,几乎可以用于求解任何可计算的问题。算法的执行过程就像是在迷宫中搜索一条通往出口的路线,总是沿着某一方向向前试探,若能走通,则继续向前进;如果走不通,则要做上标记,换一个方向再继续试探,直到得出问题的解,或者所有的可能都试探过为止。

相关标签: 编程