八皇后问题的扩展,任意数量皇后问题的较快速解法

    今天看到一个简洁的例子来描述八皇后问题的文章,使用stl算法next_permutation来对解全排列并分别验证,代码上确实简洁,不过感觉此法在运算中做了很多无谓的工作,效率上应该不佳。不过,在处理八个皇后的情况下,还是能够很快处理出所有解的,但是皇后数量多了的话,就是极大延长求解时长。

    八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

    我这里做了一个算法,在一定程度上减少了重复计算,相信算法还有继续优化的空间:

#include <tchar.h>
#include <stdio.h>

#define MAX_ITEM_COUNT      100

#ifndef __cplusplus
typedef int bool;
#define true (1)
#define false (0)
#endif

#define sTopLeft          "┌"
#define sTopRight         "┐"
#define sBottomLeft       "└"
#define sBottomRight      "┘"
#define sTop              "┬"
#define sLeft             "├"
#define sBottom           "┴"
#define sRight            "┤"
#define sVertical         "│"
#define sHorizontal       "─"
#define sCross            "┼"

//输出函数
void print_result(int map[], int item_count)
{
    int i, j;

    printf(sTopLeft);
    for (i = 0; i < item_count - 1; i++)
    {
        printf("%s%s", sHorizontal, sTop);
    }
    printf("%s%s\n", sHorizontal, sTopRight);

    for (i = 0; i < item_count; i++)
    {
        printf(sVertical);
        for (j = 0; j < item_count; j++)
        {
            if (j == map[i])
            {
                printf(" *%s", sVertical);
            }
            else
            {
                printf("  %s", sVertical);
            }
        }

        printf("\n");

        if (i != item_count - 1)
        {
            printf(sLeft);
            for (j = 0; j < item_count - 1; j++)
            {
                printf("%s%s", sHorizontal, sCross);
            }
            printf("%s%s\n", sHorizontal, sRight);
        }
    }

    printf(sBottomLeft);
    for (i = 0; i < item_count - 1; i++)
    {
        printf("%s%s", sHorizontal, sBottom);
    }
    printf("%s%s\n", sHorizontal, sBottomRight);
}

//检验是否是合法情形,只检验第index行即可
bool check_cross(int map[], int item_count, int index)
{
    int x = map[index];
    int y = index;
    int row = 0;

    for (; row < index; row += 1)
    {
        if (map[row] == x)
        {
            return false;
        }
        else
        {
            int xd = x - map[row];
            int yd = y - row;

            if (xd == yd || xd + yd == 0)
            {
                return false;
            }
        }
    }

    return true;
}

//更深的视图
int do_deep(int map[], int index)
{
    map[++index] = 0;

    return index;
}

//下一个视图
int do_next(int map[], int item_count, int index)
{
    map[index] += 1;

    if (map[index] < item_count)
    {
        return index;
    }

    index -= 1;

    if (index < 0)
    {
        return -1;
    }

    return do_next(map, item_count, index);
}

//求解函数,参数为皇后数量,和是否得到一个解就退出
bool Resolve(int item_count, bool get_one_exit)
{
    int map[MAX_ITEM_COUNT] = {0};
    int index = 0;

    if (item_count < 1 || item_count > MAX_ITEM_COUNT)
    {
        return false;
    }

    while (true)
    {
        bool cross_ok = check_cross(map, item_count, index);

        if (cross_ok && index == item_count - 1)
        {
            print_result(map, item_count);

            if (get_one_exit)
            {
                break;
            }
        }

        if (cross_ok && index < item_count - 1)
        {
            index = do_deep(map, index);
        }
        else
        {
            index = do_next(map, item_count, index);
        }

        if (index == -1)
        {
            break;
        }
    }

    return true;
}

int _tmain()
{
    //
    return !Resolve(8, true);
}

    附:28个皇后情况下的一个解:


    8皇后问题的所有解有92种,这里就不一一列举了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值