大家好,我是爱分享的小蓝,欢迎交流指正~
🔎题目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-八皇后·改
样例输入
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)
读码上万行,下键如有神,撸起袖子加油干!