Python蓝桥杯练习13——n皇后问题

【题目描述】

有一个N*N的矩阵棋盘和N个棋子,现在需要将N个棋子按要求放置在矩阵方格中。

要求:

1、任意两颗棋子不能在同一行

2、任意两个棋子不能在同一列

3、任意两个棋子不能在同一对角线上(下面的红线都是对角线)

根据以上要求,问N个棋子放置到N*N矩阵中有多少种放置方案?

【输入描述】

输入一个正整数N(1<N<11),表示N*N的矩阵方格和N个棋子数量。

【输出描述】

输出N个棋子按要求放置到N*N的矩阵中,有多少种放置方案?

【解题思路】

这要用到dfs来做

首先放置一颗棋子,从第一行开始放置,放置后该行就不能放置其他棋子来,然后每一行放的棋子通过一列一列的方式去检查是否可以放置,跳转到下一行,依次类推,如果下一行都标记不能放置的话,则回溯到上面的操作,依次进行向下标记;如果标记到最后一行,则统计次数,再清空矩阵,直到全部走完。

因为执行的每一趟操作都是类似的,所以可以增加一个递归来计算

设置一个函数,递归的开始条件从第一行开始,可以放置,则跳转到下一行。。。

递归的退出条件是:最后一行,或者下一行没有可以走到点的时候退出

图解

1.首先在第一行第一列放置一个棋子,将所在的对角线,行和列都标记不能放置。 

2.接着跳转到第二行,重复第一步的操作

3.当跳转到下一行的时候,发现都标记了不能放置,则表示无法走通,这一趟不行,回溯到上一步,清空第二部的所有标记,进行另外一个点的放置。

4.接着再跳转到第三行,再进行标记,标记后发现第四行 也以及不可放置,所以这条路也走不通,则清空,回溯到上面新的点再进行操作,以此类推。直到找到能标记到最后一行的点,计数。

直到走到这步才算完整的一条路,得出第一条摆放方式

 


【代码运算】 

n=4

#用来表示放置的位置(下标表示第几行,数值表示第几列)
# ->place[1]=2 表示在第二行第三列标记了数
place = [0 for _ in range(n)]

#用于表示第n列是否被标记 -> flag[1]=1 表示第2列被标记为1
flag=[0 for _ in range(n)]

#表示对角线是否被标记
d1=[0 for _ in range(2*n-1)]#上对角线 行加上列

d2=[0 for _ in range(2*n-1)]#下对角线 行减列加n减1

#计数
count=0

def search(row):#行
    global count #标记全局变量
    for col in range(n):
        
        if flag[col]==0 and d1[row+col]==0 and d2[row-col+n-1]==0:# 0表示没有被标记
            place[row] = col #在第row行第col列标记

            #列,对角线标记不能X
            flag[col]=1
            d1[row+col]=1
            d2[row-col+n-1]=1
            #如果不是最后一行,继续寻找
            if row<n-1:
                search(row+1)
            else:
                count+=1
            #最后一行执行结束,清空,继续寻找下一个
            flag[col]=0
            d1[row+col]=0
            d2[row-col+n-1]=0
search(0) #从第一行开始寻找
print(count) #2

上对角线——一共有2*n-1条  可以观察到,行加列=对角线上的值

 下对角线——也是2*n-1条,计算对角线上的值是——row-col+n-1 


 如果想要打印结果,只需要增加一个打印的函数,在每次统计次数时加一个打印即可

【运行代码】

n=4

#用来表示放置的位置(下标表示第几行,数值表示第几列)
# ->place[1]=2 表示在第二行第三列标记了数
place = [0 for _ in range(n)]

#用于表示第n列是否被标记 -> flag[1]=1 表示第2列被标记为1
flag=[0 for _ in range(n)]

#表示对角线是否被标记
d1=[0 for _ in range(2*n-1)]#上对角线 行加上列

d2=[0 for _ in range(2*n-1)]#下对角线 行减列加n减1

#计数
count=0
#打印函数
def printf(place):
    #创建一个n行n列的矩阵
    for i in range(n):
        for j in range(n):
            
            if place[i]==j:
                print('*',end=' ')
            else:
                print('0',end=' ')
        print() #每行换行
    print() #每个矩阵换行
    



def search(row):#行
    global count #标记全局变量
    for col in range(n):
        
        if flag[col]==0 and d1[row+col]==0 and d2[row-col+n-1]==0:# 0表示没有被标记
            place[row] = col #在第row行第col列标记

            #列,对角线标记不能X
            flag[col]=1
            d1[row+col]=1
            d2[row-col+n-1]=1
            #如果不是最后一行,继续寻找
            if row<n-1:
                search(row+1)
            else:
                count+=1
                #打印
                printf(place)
            #最后一行执行结束,清空,继续寻找下一个
            flag[col]=0
            d1[row+col]=0
            d2[row-col+n-1]=0
search(0) #从第一行开始寻找
print(count) #2

【运行结果】

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值