排列
[题目链接]https://www.acwing.com/problem/content/825/
题意
求将1~n个整数排成一排有多少种不同的排法
思路
- 共3位数,有三个能够存放数字的位置,用u代表第几个能存放数字的位置
- 从第一个位置,即从u=1开始递归,从数字1到3进行考虑所有情况,放过的数字则不能进行第二次放置
- 当放置到最底层,即u=n时,开始返回进行上一层的递归(返回现场),同时取消标记第三个位置存放的数
递归搜索树
搜索历程
坑点
- 按照字典序排列
字典序——按照字典中的顺序排列,如在英语字典中以a、b、c……z的顺序排列,对于数字则是以1、2、3…n的顺序排列
实现步骤
- 定义两个数组,一个为st(state)记录每个数的状态,即该数字是否被标记,默认st数组的值为0(没有被标记),当被标记时,数组值则为1,另一个为q,记录每一个填入u位置的数字
- 在主函数中定义一个dfs函数,初始值为1,即u的值,从第一个能够存放数字的位置开始
- 当u>n,即超出最底层时,说明已经数字已经填到了最后一个空,此时可以输出数组q中的数字
- 当u没有到最底层时,利用for循环从1到n开始给每一个u上的数赋值
- 判断赋值的数是否被标记,当数组st的值不为0时,则说明该数没有被标记,可用,此时将 i 赋值给q[u](从1到n循环遍历每一个位置上被放置的数字)
- 此时,将数组st的值改为1,表示上述填过的数字被标记为已使用过,后面不可用
- 继而利用dfs(u+1)进行下面一层一层的递归
- 当从每个下一层出来,返回上一层,进行上一个存放数字位置的填空时,此时的数字状态需被改为未被标记的状态,即st[i]=0。
代码
#include <bits/stdc++.h>
using namespace std;
int n; //输入的整数n
int st[15]; //判断数字状态为0还是1,默认值为0,表示被使用过,为1则表示没有使用过
int q[10]; //表示输出的n个数字排成的一排
void dfs (int u)
{
if (u>n) //当数字已经填到大于n的空时
{
for(int i=1;i<=n;i++)
{
cout<<q[i]<<" "; //输出当前的数字
}
cout<<endl;
}
else
{
for(int i=1;i<=n;i++)
{
if (!st[i]) //否则,当st[i]没有被使用过时
{
q[u]=i; //从1到n循环遍历每一次存放数字的位置
st[i]=1; //在当前位置存放一个数后,该数字状态被标记为已使用过(字典序要求),后面不可用
dfs(u+1); //进行下一层的函数递归
st[i]=0;//从下一层出来往上返回进行上一个存放数字位置的填空时,此时的数字状态变为未被标记
}
}
}
}
int main ()
{
cin>>n;
dfs(1); //定义一个函数,初始值为1,因为从第一个位置开始填数字
return 0;
}