八皇后

N皇后问题是一个经典的问题,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行、同一列、同一斜线上的皇后都会自动攻击)

回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。首先就是在棋盘上如何判断两个皇后是否能够相互攻击,在最初接触这个问题时,首先想到的方法就是把棋盘存储为一个二维数组,然后在需要在第i行第j列放置皇后时,根据问题的描述,首先判断是在第i行是否有皇后,由于每行只有一个皇后,这个判断也可以省略,然后判断第j列是否有皇后,这个也很简单,最后需要判断在同一斜线上是否有皇后,按照该方法需要判断两次,正对角线方向和负对角线方向,总体来说也不难。但是写完之后,总感觉很笨,因为在N皇后问题中这个函数的使用次数太多了,而这样做效率较差。上网查看了别人的实现之后大吃一惊,使用一个一维数组来存储棋盘,在某个位置上是否有皇后可以相互攻击的判断也很简单。

把棋盘存储为一个N维数组a[N],数组中第i个元素的值代表第i行的皇后位置,这样便可以把问题的空间规模压缩为一维O(N),在判断是否冲突时也很简单,首先每行只有一个皇后,且在数组中只占据一个元素的位置,行冲突就不存在了,其次是列冲突,判断一下是否有a[i]与当前要放置皇后的列j相等即可。至于斜线冲突,通过观察可以发现所有在斜线上冲突的皇后的位置都有规律即它们所在的行列互减的绝对值相等,即| row – i | = | col – a[i] |(之前自己做过的代码太丑了,所以贴个别人的代码。)

#include <iostream>
using namespace std;

#define NUM 8
static int gEightQueen[8] = {0};
static int gCount = 0;

void print()
{
    int outer;
    int inner;

    for (outer = 0; outer < NUM; outer++)
    {
        for(inner = 0; inner < gEightQueen[outer]; inner++)
            printf("*");
        printf("#");

        for(inner = gEightQueen[outer] +1; inner < NUM; inner++)
            printf("*");
        printf("\n");
    }
    printf("=====================================\n");
}

int checkPosValid(int loop, int value)
{
    int index;
    int data;

    for(index = 0; index < loop; index++)
    {
        data = gEightQueen[index];

        if(value == data)
            return 0;

        if((index + data) == (loop + value))
            return 0;

        if((index - data) == (loop - value))
            return 0;
    }

    return 1;
}

void eightQueen(int index)
{
    int loop;

    for(loop = 0; loop < NUM; loop++)
    {
        if(checkPosValid(index,loop))
        {
            gEightQueen[index] = loop;

            if(7 == index)
            {
                gCount++;
                print();
                gEightQueen[index] = 0;
                return;
            }

            eightQueen(index + 1);
            gEightQueen[index] = 0;
        }
    }
}

int main()
{
    eightQueen(0);
    printf("total = %d\n", gCount);
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值