问题描述
输入一个指定的数n(n为1-9之间的整数),输出1~n之间的全排列
比如输入3,输出123的全排列:123、132、213、231、312、321;输入4,输出1234的全排列:….
当然这个问题也可以这样描述: 有编号1、2…n的n张扑克牌(n为1-9之间的整数),编号1、2…n的n个盒子。将这n张扑克牌分别放到这n个盒子里面,并且每个盒子有且只能放一张扑克牌。一共有多少种不同的放法?
最简单的方法当然就是暴力枚举了,pass掉。
这里我们用 深度优先搜索(Depth First Search,DFS) 解题.
深度优先搜索的关键在于解决”当下应该怎么做”。至于”下一步如何做”则与”当下该如何做”是一样的
以下的代码就是DFS的基本模型
1 2 3 4 5 6 7 8 9 10 11 12 13
| void dfs(int step) { 判断边界 尝试每一种可能
for(i=1; i<n; i++) { 继续下一步 dfs(step+1); }
返回 }
|
上代码
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
| #include <stdio.h>
int a[10],book[10],n;//此处特别说明一下 ,C语言的全局变量在没有赋值以前默认为0,因此这里的book数组无需全部再次赋值为0
void dfs(int step) // step表示现在站在第几个盒子前 { int i; if(step == n+1) // 如果站在第 n+1 个盒子前面,则表示前n个盒子已经放好扑克牌 { //输出一种排列 (1-n号盒子中的扑克牌编号) for(i=1; i<=n; i++){ printf("%d",a[i]); } printf("\n");
return; //返回之前的一步 (最近一次调用dfs函数的地方) }
// 此时站在第step个盒子前面,应该放哪张牌呢? // 按照1,2,3....n的顺序一一尝试
for(i=1; i<=n ; i++) { //判断扑克牌 i 是否在手上 if(book[i] == 0) // book[i]等于0表示i号扑克牌在手上 { // 开始尝试使用扑克牌 i a[step] = i; // 将 i 号扑克牌放入到第 step 个盒子中 book[i] = 1; //将 book[i] 设为 1 ,表示 i 号扑克牌已经不在手上
// 第 step 个盒子已经放好扑克牌,接下来需要走到下一个盒子面前 dfs(step + 1); //这里通过函数的递归调用来实现 (自己调用自己) book[i] = 0; // 这是非常重要的一步,一定要将刚才尝试的扑克牌收回,才能进行下一次尝试 } }
return; }
int main(int argc, char *argv[]) { scanf("%d",&n); // 输入的时候要注意 n 为1-9之间的整数 dfs(1); //首先站在 1 号小盒子面前 //getchar();getchar(); return 0; }
|
参考