两种不同方式解决八皇后问题

问题描述

八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

解决思路

这个问题可以有两种解决方法,一种是使用递归,比较简单易懂,另一种是使用栈,利用栈的特性避免了递归的使用,从而提高了效率(递归的虽然简单易写,但是其效率往往较低)。

具体实现

首先将节点的坐标定义为结构体:

typedef struct {
 int x;
 int y;
} Coord;

定义好judge函数(用于判断对应点坐标是否可以放置皇后):

bool judge(SqStack S, int x, int y) {
    SqStack m = S;
    while (!StackEmpty(m)) {
        Coord e;
        e = Pop(m);
        if ((e.x == x) || (abs(e.x - x) == abs(e.y - y))) {
            return false;//如果不行返回false
        }
    }

    return true;//如果可以返回true
}

递归

void Recursive(SqStack &S, int y) {

    if (StackEmpty(S)) {
        for (int i = 1; i <= N;   i) {
            Coord e;
            e.x = i;
            e.y = 1;
            Push(S, e);
            Recursive(S, 2);
            Pop(S);
        }
    } else if (Full(S)) {
        StackTraverse(S);
        n  ;
        return;
    } else {
        for (int i = 1; i <= N;   i) {
            if (judge(S, i, y)) {
                Coord e;
                e.x = i;
                e.y = y;
                Push(S, e);
                Recursive(S, y   1);
                Pop(S);
            }
        }
    }
}

这里要注意递归调用Recurive之后要pop出递归之前push进去的,有进就要有出~

非递归

void Search(SqStack s) {

    int i = 1;
    bool flag;

    Coord e;
    e.x = 0;
    e.y = 1;

    while (i <= 8) {

        if (flag) {
            e.x = 0;
        }
        if (Full(s)) {
            e = Pop(s);

        }
        flag = false;

        for (int j = e.x   1; j <= 8; j  ) {
            if (judge(s, j, i)) {
                Coord e2;
                e2.x = j;
                e2.y = i;
                Push(s, e2);
                //  cout << "a" << i << "(" << e.y << "," << e.x << ") ";
                flag = true;
                break;
            }
        }


        if (flag) {
            if (i == 8) {
                StackTraverse(s);
                num  ;

            } else {
                i  ;
            }
        } else {
            i--;
            e = Pop(s);
            if (i == 0) {
                break;
            }
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值