欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《算法笔记》8.1小节——搜索专题->深度优先搜索(DFS)之[递归入门]全排列

程序员文章站 2022-06-06 08:01:35
...

题目描述 排列与组合是常用的数学方法。
先给一个正整数 ( 1 < = n < = 10 )
例如n=3,所有组合,并且按字典序输出:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
输入输入一个整数n( 1<=n<=10)输出输出所有全排列
每个全排列一行,相邻两个数用空格隔开(最后一个数后面没有空格)样例输入
3
样例输出
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
题目链接
codeup.cn/problem.php?cid=100000608&pid=0
解题思路
假如有编号为1 、2、3 的3 张扑克牌和编号为l 、2 、3 的3 个盒子。
现在需要将这3 张扑克牌分别放到3 个盒子里面,并且每个盒子有且只能放一张扑克牌。那么一共有多少种不同的放法呢?
首先 我们应该设置一个标志数组 book 记录当前数字的扑克牌是否被使用过。0表示未使用,1表示已经使用了。 然后用一个数组a 表示盒子并且初始化a[i]=i。
设计递归
递归边界——step等于n+1,即n个盒子里面全部装满了数字,然后打印这一组盒子里的数字即可。递归主体——第step个盒子放编号为i的数字,然后将该编号i的数字标记为1,用来表示该数字已经使用。然后再第step+1的盒子里放数字,使用过的数字不能再使用,使用未使用过的数字,如此递归下去,直到到达边界即可。最终将标记过的数字回溯,即类似迷宫的岔路口,到达某一死胡同后,返回到最初的岔路口,进行下一种走法,即下一种全排列。
代码如下:

#include<stdio.h>
int n,a[10],book[10];//特别说明c语言全局变量没有赋值默认为 0,无需再次初始化;
void dfs(int step)//step 表示当前在第几个位置
{ int i; 
    if(step==n+1)//如果step==n+1表示前n个数字已经放好
    {  //输出一种全排列
        for(i=1;i<=n;i++)
        {
            if(i==n) printf("%d\n",a[i]);
            else printf("%d ",a[i]);
        }
    return;
    }
    
    for(i=1;i<=n;i++)//每次搜索都从1-n 一一尝试
    {
        if(book[i]==0)//判断次数字是否用过
        {
            a[step]=i;//存储当前位置的数字,以便满足条件输出
            book[i]=1;//当前数字已用过,改变标志,以防重用
            dfs(step+1);//放好当前位置数字之后,安排下一个数字
            book[i]=0;//回溯,当满足一种全排列后,进行下一种尝试
        }
    }
    return ;
}
int main()
{ 
    scanf("%d",&n);//输入只能为1-9之间的整数,表示1-n的全排列
    dfs(1);//从第一个位置开始
    return 0;
} 

补充:
对于本题其实就是利用深度优先搜索进行解题的,每一种全排列可看成迷宫的一条死底胡同路径,到达死胡同底,然后再返回到最初的岔路口,再进行下一次深度探索,最终达到迷宫的出口。
对于递归的算法代码理解,画出递归树即可,也要注意回溯。设计递归,要知道递归边界,递归公式(即递归的主要思想)(设计递归就是多看大神的代码,跟数学一样,越菜越爱玩,久而久之自己也变成更强的菜鸟了(滑稽))

相关标签: 深度优先收索