排列数字
给定一个整数 n,将数字 1∼n排成一排,将会有很多种排列方法。
现在,请你按照字典序将所有的排列方法输出。
输入格式:
共一行,包含一个整数 n。
输出格式:
按字典序输出所有排列方案,每个方案占一行。
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
这是一道非常经典的dfs的例题,要求我们根据输入的数字去输出这个数量的全排列组合。
我们以示例输入来讲解,
首先先抽象出n个空格格,这里是3,在这三个格格中依次填充上我们1~n的数字,就构成了上图所画出来的树的结构,最终在最后的结点输出即可。
那么问题的关键就是
1.在何时输出?
2.在何时回溯到上一个节点?
针对问题1:
我们的要求是在最后一个子节点进行输出,所以当填充的数和输入的n相当时就说明填满了,要输出了。
针对问题2:
在输出最下层的结点之后,当前的函数会return到上一层,问题的关键在于理解,每次递归的每一个函数是代表树中的一个结点的。然后通过循环进行下一个数字的填充。
源码:
n=int(input())
path=[0]*n
st=[False]*(n+1)
def dfs(u):
if u==n: #当u==n 说明已经准备遍历到第n个数字的下一个了(u是从0开始的)
for i in path:
print(i,end=" ")
print()
return
else:
# u!=n 则遍历一下有那些数字还可以用
for i in range(1,n+1):
if st[i]!=True:
path[u]=i
st[i]=True
dfs(u+1)
#恢复现场
path[u]=0
st[i]=False
dfs(0)
n-皇后问题
n−皇后问题是指将 n个皇后放在 n×n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
现在给定整数 n,请你输出所有的满足条件的棋子摆法。
输入格式:
共一行,包含整数 n。
输出格式:
每个解决方案占 n行,每行输出一个长度为 n的字符串,用来表示完整的棋盘状态。
其中 .
表示某一个位置的方格状态为空,Q
表示某一个位置的方格上摆着皇后。
每个方案输出完成后,输出一个空行
输入样例:
4
输出样例:
.Q..
...Q
Q...
..Q.
..Q.
Q...
...Q
.Q..
在理解了上一个题的基础之上,在来看这个题会好理解很多。
与上一个题相似,上面是判断某个数字是否用过,皇后问题是判断这个皇后是否存在同一列或同一行或同一斜线上。
n=int(input())
a=[["." for i in range(n)] for j in range(n)]
col=[0]*n
dg=[0]*(2*n)
undg=[0]*(2*n)
def dfs(u):
#先找边界条件
if u==n:
for i in range(n):
for j in range(n):
print(a[i][j],end="")
print()
print()
return
#开始以每列遍历 全排列寻找皇后的合法位置
for i in range(n):
if((col[i]==0) and (dg[i-u+n]==0) and (undg[i+u]==0)):
a[u][i]="Q"
col[i]=dg[i-u+n]=undg[i+u]=1
dfs(u+1)
#回溯时 恢复现场
a[u][i]="."
col[i]=dg[i-u+n]=undg[i+u]=0
dfs(0)