【蓝桥模板】——滴,你的「深度优先搜索」模板已到账(DFS八皇后模板 )

大家好,我是爱分享的小蓝,欢迎交流指正~ 


🔎题目1-八皇后

传送门: [USACO1.5]八皇后 Checker Challenge - 洛谷

   样例输入

6

   样例输出

2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4


📖题解

难度系数:⭐⭐

考察题型:搜索

涉及知识点:DFS

面对DFS题,其实最好的办法是套模板,这里给大家奉上思路流程图~

友友在评论区提问,所以小蓝在这解释一下细节问题:(╹ڡ╹ )
b[j]     存储一列→的棋子 
c[i+j]   存储左斜↗的棋子 i+j是一个定值
d[i-j+n] 存储右斜↘的棋子 i-j是一个定值,不过会出现负数,所以整体加个n

根据上图,举个栗子你就懂了✪ ω ✪

比如皇后占领了坐标(2,4)那个格子,

b[j]=1 b[4]=1代表第四列↓被皇后占领了,其他棋子不能放。

那么对角线用什么数据结构表示呢?其实可以用数学规律表示。

c[i+j]=1 c[2+4]=1 代表第6左斜↗被皇后占领了.

找一找左斜经过的坐标(5,1) (4,2) (3,3) (2,4) (1,5),发现规律i+j都是定值6.

以此类推,所有的左斜i+j都是定值k,

所以列表c存储的就是它们的和,而且和都不同,就能区分出不同的对角线了。

d[i-j+n]=1 d[2-4+6]=4 代表第4个右斜↘被皇后占领了。

跟上面一个道理,i-j也是一个定值,友友可以自己举个栗子找找验证一下,

不过要加上n,是因为两数i,j相减会出现负数,列表索引不能为负,所以统一加个n.

其实加什么都可以,只要不让列表索引出现负数即可。

搞懂上面的原理,小蓝的脑子都清楚多啦~\^o^/

🍞代码

#DFS-八皇后模板
n=int(input())#n*n的格子
a,b,c,d=[0]*100,[0]*100,[0]*100,[0]*100
#a:行↓ b:列→ c:左斜↗ d:右斜↘ 
cnt=0
def dfs(i):
    global cnt,n,a,b,c,d
    if i>n:         #越界条件
        cnt+=1
        if cnt<=3:  #前三次打表
            for i in range(1,n+1):
                print(a[i],end=" ") 
            print() 
        return
    for j in range(1,n+1):
        if b[j]==0 and c[i+j]==0 and d[i-j+n]==0:#判断 没有皇后占领
            b[j],c[i+j],d[i-j+n]=1,1,1           #标记 占领3个列表
            a[i]=j                               #赋值 皇后位置确定
            dfs(i+1)                             #递推 寻找下一个皇后
            b[j],c[i+j],d[i-j+n]=0,0,0           #回溯 清除标记
dfs(1)                                           #开启递归
print(cnt)                                       #解的总数

'''
样例输入:
6
样例输出:
2 4 6 1 3 5 
3 6 2 5 1 4 
4 1 5 2 6 3 
4
'''

 啊这···最后两组超时了,看了一眼测试案例,

应该是12和13没出来,这时一个大胆的想法冒出来( •̀ ω •́ )✧我要打表! 

n=int(input())
a,b,c,d=[0]*100,[0]*100,[0]*100,[0]*100
cnt=0
def dfs(i):
    global cnt,n,a,b,c,d
    if i>n:         #越界条件
        cnt+=1
        if cnt<=3:  #打印前三次
            for i in range(1,n+1):
                print(a[i],end=" ") 
            print() 
        return
    for j in range(1,n+1):
        if b[j]==0 and c[i+j]==0 and d[i-j+n]==0:#满足条件
            b[j],c[i+j],d[i-j+n]=1,1,1           #标记
            a[i]=j                               #赋值
            dfs(i+1)                             #递推
            b[j],c[i+j],d[i-j+n]=0,0,0           #回溯
if n==12:
    print("1 3 5 8 10 12 6 11 2 7 9 4")
    print("1 3 5 10 8 11 2 12 6 9 7 4")
    print("1 3 5 10 8 11 2 12 7 9 4 6")
    print(14200)
elif n==13:
    print("1 3 5 2 9 12 10 13 4 6 8 11 7")
    print("1 3 5 7 9 11 13 2 4 6 8 10 12")
    print("1 3 5 7 12 10 13 6 4 2 8 11 9")
    print(73712)
else:
    dfs(1)
    print(cnt)

特殊情况特殊处理——打表也是个不错的选择~嘿嘿。


 🔎题目 2-八皇后·改

传送门:蓝桥杯算法提高VIP-8皇后·改 - C语言网

样例输入

1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
48 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64

样例输出

260

📖题解

难度系数:⭐⭐

考察题型:搜索

涉及知识点:DFS


🍞代码

maps=[[int(i) for i in input().split()] for j in range(8)]
b,c,d=[0]*100,[0]*100,[0]*100
ans=-float("inf")#赋初值为最小值
def dfs(i,maxv):
    global ans,b,c,d
    if i==8:#越界条件
        ans=max(ans,maxv)
        return
    for j in range(8):
        if b[j]==0 and c[i+j]==0 and d[i-j+8]==0:#满足条件
            b[j],c[i+j],d[i-j+8]=1,1,1           #标记
            dfs(i+1,maxv+maps[i][j])             #递推
            b[j],c[i+j],d[i-j+8]=0,0,0           #回溯
dfs(0,0)
print(ans)


 读码上万行,下键如有神,撸起袖子加油干!

  • 34
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蓝刷题

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值