八皇后 深度优先 广度优先 位运算

对于八皇后问题,大家应该都不陌生,只要接触过算法的,必然都会接触到这到题。对于八皇后的问题不在此叙述,可以直接百度。对于八皇后问题的解决思路,可以直接根据题目的要求便可以得到。在这里插入图片描述
总的来说,就是下一个皇后放置的点不能在上图所画的实线当中。
这里我仅考虑有多少种放置方法,而不考虑如何去放置。

深度优先搜索

DFS版本的解法应该是最普遍,直接通过回溯便可以解决。

def dfs(queues, xy_sum, xy_dif, num):
    global count
    row = len(queues)
    if row == num:          # 所有皇后都放置完成
        count += 1
    for col in range(num):  # 一列一列的尝试放置
        if col not in queues and row+col not in xy_sum and row-col not in xy_dif:  # 列不冲突,左右斜线都不冲突
            dfs(queues+[col], xy_sum+[row+col], xy_dif+[row-col], num)  # 下一层的皇后

global count
count = 0
dfs([], [], [], 4)
print(count)

广度优先搜索

广度优先与深度优先作为一对兄弟,竟然能使用深度优先搜索来实现,则必然也可通过广度优先来实现(感谢好兄弟的提醒)

def bfs(num):
    global count
    queues = []   # 皇后点的队列
    # 初始化所有可能的点  也就是第一行中的所有点
    for i in range(num):    
        queues.append(tuple((0, i, [0], [i], [0+i], [0-i]))) # 点x, 点y,行,列,xy_sum, xy_dif
    while queues:
        row, col, rows, cols, xy_sum, xy_dif = queues.pop(0)
        if row == num-1:  # 到达最后一行了,将结果加1,直接下一轮
            count += 1
            continue
        row += 1
        for col in range(num):  # 判断每个位置是否可以存放
            if row not in rows and col not in cols and row+col not in xy_sum and row-col not in xy_dif:
                queues.append(tuple((row, col, rows+[row], cols+[col], xy_sum+[row+col], xy_dif+[row-col])))
    return count

global count
count = 0  
bfs(8)
print(count)

位运算

对于八皇后问题的解决,还有一种最不常见的方法,便是位运算,其实位运算的整体思路与DFS相似,只是通过使用位运算来进行判断以提高程序的运行速度。

def bitcom(row, col, xy_sum, xy_dif, num):
    global count
    if row == num:
        count += 1
    bits = (~(col|xy_sum|xy_dif)) & ((1<<num)-1)  # 得到有效空位 不放在col,xy_sum, xy_dif线上 & 获取后num位可放置的位置  
    while bits:
        p = bits & -bits  # 从后往前逐个获取可放置的位置  这边也就是从后朝前获取1的位置
        bitcom(row+1, col|p, (xy_sum|p)<<1, (xy_dif|p)>>1, num)   # col|p 为去掉刚刚放置的列   (xy_sum|p)<<1 下一行种当前斜线上不能放的位置置0
        bits = bits & (bits-1)  # 清零最低为的1,即将已放置过的位置置0

global count
count = 0  
bitcom(0, 0, 0, 0, 8)
print(count)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值