八皇后问题(启发式搜索)

        八皇后问题是回溯算法的典型案例,在回溯法中,常常是盲目搜索,耗费过多的搜索时间。在本次实验中,使用了启发式搜索,搜索时不是任取一个分支,而是选择最佳的分支往下搜索。


目录

前言:

一、初始化参数:

二、检测某位置是否可以放置皇后

三、某位置放置皇后的调整

四、删除某位置的皇后

五、计算剩余行所剩可以放置皇后位置的个数

六 、呈现最后的矩阵

七、启发式搜索

八、完整代码:


前言:

        XDU作业:启发式算法解决八皇后问题

问题描述:问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。




一、初始化参数:

n:代表皇后的个数,因为规定每行放置一个皇后,所以也可以理解为行数。

checkboard:代表最后呈现出来的矩阵,这里用‘0’表示该位置为空位,既没有放置皇后;用‘1’代表该位置已经放置皇后了。

queen_position: 代表每一行皇后所在改行的列数,因为题目默认是8行,所以设置了8个元素的数组初始值为-1,如果第一行的元素放在第1列,则queen_position[0] = 1。

available_position: 检测该行的某列是否满足可以放置皇后的条件,为三行十五列的矩阵,available_position[0][i]代表i列是否已经放置过皇后了,available_position[1][i]代表该位置的右对角线是否放置过皇后,available_position[2][i]代表该位置左对角线是否放置过皇后。

fx:代表代价。即若该位置皇后后,后面可以放置皇后的位置还有多少个。

answer: 代表该行是否符合可以放置皇后。




二、检测某位置是否可以放置皇后

输入函数的参数为行数和列数。

如果该位置的左对角线,右对角线,及该位置所在的列数都没有放置过皇后,则满足条件。

返回True,则该位置可以放置皇后,返回False,则该位置不满足放置皇后的条件。

#to test the position of [row, col] could be able to place queen or not
def queen_admission(row, col):
    global available_position
    global queen_position
    if(available_position[0][col] and available_position[1][row+col] and available_position[2][row-col+n-1]):
        return True
    else:
        return False

三、某位置放置皇后的调整

输入函数的参数为行数和列数。

在该位置放置皇后,则该列的0要置1,左对角线和右对角线的相应的位置都要置1。

并记录该行皇后所在的位置。

#place the queen into [row,col]
def place_queen(row, col):
    global available_position
    global queen_position
    queen_position[row] = col
    available_position[0][col] = 0
    available_position[1][row+col] = 0
    available_position[2][row-col+n-1] = 0
    return None

四、删除某位置的皇后

输入函数的参数为行数和列数。

与放置皇后的操作相反,将该行皇后的位置置-1,及不确定该行皇后所在的列数。

依次将该位置所在的列数,左右对角线相应的位置清零。

#delete the queen in [row,col]
def delete_queen(row, col):
    global available_position
    global queen_position
    queen_position[row] = -1
    available_position[0][col] = 1
    available_position[1][row+col] = 1
    available_position[2][row-col+n-1] = 1
    return None

五、计算剩余行所剩可以放置皇后位置的个数

输入函数的参数为行数和列数。

依次遍历剩余行所有的列数,并判断每个位置是否为可以放置皇后位置的位置,如果满足条件则计数+1。

#find the available number
def commute_beneficial(row, col):
    global n
    global available_position
    remain_available_number = 0
    place_queen(row, col)
    for i in range(row+1, n):
        for j in range(n):
            if(queen_admission(i, j)):
                remain_available_number += 1
    delete_queen(row, col)
    return remain_available_number

六 、呈现最后的矩阵

取每行皇后所在列数,遍历checkboard并更改其值,最后输出checkboard。

#presentation the checkerboard
def final_show():
    global n
    global queen_position
    global checkerboard

    for i in range(n):
        queen_position[i] = np.argmax(fx[i])
    for i in range(n):
        for j in range(n):
            if j == queen_position[i]:
                checkerboard[i][j] = 1
    print(checkerboard)

运行结果:

 


七、启发式搜索

        该算法采用递归的思想,从第一行开始,直到最后一行,每列所取的列数为fx最大的那个列数。如果到某一行发现没有所满足的列数,则返回上一行,取fx次大的列数继续直到cur的值为8。

#启发式搜索
def search(cur):
    global n
    global queen_position
    global checkerboard
    global fx
    global answer

    if(cur == n):
        answer = True
    else:
        flag = False
        for i in range(n):
            if(queen_admission(cur, i)):
                flag = True
                fx[cur][i] = commute_beneficial(cur, i)

        if(flag):
            while(answer == False):
                max = -1
                max_col = -1
                max = np.max(fx[cur])
                max_col = np.argmax(fx[cur])

                if(max == -1):
                    fx[cur-1][queen_position[cur-1]] = -1
                    return
                queen_position[cur] = max_col
                place_queen(cur, max_col)
                search(cur+1)
                delete_queen(cur, max_col)
        else:
            fx[cur-1][queen_position[cur-1]] = -1

八、完整代码:

'''
由于在某一步放置某个皇后时,可能有多个空格可以使用,所以定义启发式函数:

        fx = 剩下未放行中能够用来放皇后的空格数

    如果第i行的皇后放在第j列合法,计算启发式函数的值fx(i,j)。计算出第i行所有空格的fx后,
    将第i个皇后放到第i行中那个与前面i-1个皇后不在同一列或对角线上且fx值最大的空格中(相同时取第一个)。
    如果当前策略无法求解,则回溯至上一步,选择fx值次大的空格放置皇后,依次类推,直至找到一个合法的解。
'''

import numpy as np


n = 8
checkerboard = np.zeros((8, 8), dtype=int)
queen_position = np.zeros(8, dtype=int)-1
available_position = np.ones((3, 15), dtype=int)
fx = np.zeros((n, n), dtype=int) - 1
answer = False

#to test the position of [row, col] could be able to place queen or not
def queen_admission(row, col):
    global available_position
    global queen_position
    if(available_position[0][col] and available_position[1][row+col] and available_position[2][row-col+n-1]):
        return True
    else:
        return False

#place the queen into [row,col]
def place_queen(row, col):
    global available_position
    global queen_position
    queen_position[row] = col
    available_position[0][col] = 0
    available_position[1][row+col] = 0
    available_position[2][row-col+n-1] = 0
    return None

#delete the queen in [row,col]
def delete_queen(row, col):
    global available_position
    global queen_position
    queen_position[row] = -1
    available_position[0][col] = 1
    available_position[1][row+col] = 1
    available_position[2][row-col+n-1] = 1
    return None

#find the available number
def commute_beneficial(row, col):
    global n
    global available_position
    remain_available_number = 0
    place_queen(row, col)
    for i in range(row+1, n):
        for j in range(n):
            if(queen_admission(i, j)):
                remain_available_number += 1
    delete_queen(row, col)
    return remain_available_number


#presentation the checkerboard
def final_show():
    global n
    global queen_position
    global checkerboard

    for i in range(n):
        queen_position[i] = np.argmax(fx[i])
    for i in range(n):
        for j in range(n):
            if j == queen_position[i]:
                checkerboard[i][j] = 1
    print(checkerboard)

#启发式搜索
def search(cur):
    global n
    global queen_position
    global checkerboard
    global fx
    global answer

    if(cur == n):
        answer = True
    else:
        flag = False
        for i in range(n):
            if(queen_admission(cur, i)):
                flag = True
                fx[cur][i] = commute_beneficial(cur, i)

        if(flag):
            while(answer == False):
                max = -1
                max_col = -1
                max = np.max(fx[cur])
                max_col = np.argmax(fx[cur])

                if(max == -1):
                    fx[cur-1][queen_position[cur-1]] = -1
                    return
                queen_position[cur] = max_col
                place_queen(cur, max_col)
                search(cur+1)
                delete_queen(cur, max_col)
        else:
            fx[cur-1][queen_position[cur-1]] = -1


if __name__ == "__main__":

    search(0)
    final_show()
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值