马上就要蓝桥杯,算法好多都不会,最近在读啊哈磊的《啊哈算法》,这本书挺通俗易懂,尤其对于我这种比较菜的人哈哈。下面就谈一谈用dfs思想解决全排列问题,所谓dfs就是深度优先搜索(Depth First Search)。
下面先给出一个dfs的基本函数模型。
void dfs(int step)
{
判断边界
尝试每一种可能 for(i=1;i<=n;i++)
{
继续下一步dfs(step+1); //这里也运用了递归思想
}
返回
}
举个例子,假如你手里有三个球分别标记1,2,3号,现在你的面前有三个盒子(同样1,2,3号),你需要将三个球放入三个盒子中,共有几种排列方式,这个当然很容易算,直接枚举就可以了,这是三位的全排列,那如果是位数比较大总不能枚举吧,所以我们需要一个程序解决这个问题,先供上代码
#include<stdio.h>
int a[10],book[10],n;//a这个数组用来当盒子装球,book数组用来标记某号球是否还在手里,n为盒子数
//c语言全局变量在没用赋值以前默认为0
void dfs(int step)
{
int i;
if(step==n+1)//表示现在站在n+1个盒子面前,前面n个盒子已经排好序
{
for(i=1;i<=n;i++)
{
printf("%d",a[i]);//输出这种排列
}
printf("\n");
return;//返回到最近一次调用dfs函数的位置
}
for(i=1;i<=n;i++)
{
if(book[i]==0)//book[i]=0表示某号球还没有放入盒子中
{
a[step]=i;//将i号球放入第step个盒子中
book[i]=1;//book[i]=1表示i号球已经不在手里
dfs(step+1);//递归调用
book[i]=0;//将之前放入的球拿出来,才可以进入下一次排列
}
}
return;
}
int main()
{
scanf("%d",&n);
dfs(1);//最先站在1号盒子面前
getchar();
getchar();
return 0;
}
看完代码如果还有点迷茫,大家可以在纸上自己模拟一下过程,比如要输出三位的全排列,先输入n=3
进入dfs函数,第一个if语句显然不成立,则马上进入for循环,当i等于1时判断 if 语句,现在1号球在手上(if语句成立),然后将1号球放入1号盒子中,之后进入dfs(2)的for循环,发现i=1时if语句不成立,因为刚才已经把1号球放入了1号盒中,以此类推,当i等于2时成立,将2号球放入2号盒子,进入dfs(3),又将3号球放入3号箱子里,此时进去dfs(4)其实根本没有4号盒子,现在将进入第一个if语句,输出现在这种全排列----->1 2 3,这时候return到dfs(3)函数中将3号球取出,此时dfs(3)中的for循环已经进行到i=3,结束return返回dfs(2)中,再将2号球取出,此时这里的for循环还没有进行到底(此时是i=2),下一步进行i等于3循环,将刚刚取出的3号球放入2号盒子中,再进行dfs(3),把2号球放入3号盒子中,然后程序再次进入到dfs(4)中,第一个if又成立了,输出现在这种全排列----->1 3 2,然后继续return到dfs(3)中…以此类推最后输出3位的所有全排列。
下图是我运行3的全排列的截图
ps:在这个程序中最多可以输出9位的全排列,如果想输出更大的,只需要更改全局变量即可。