这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战
想要坚持写点什么,那干脆写一个系列吧。想想有什么可以写的呢?程序=算法+数据结构,可见算法的重要性。这个系列老诗力求用最简单的语言把算法讲得明明白白,由浅到深,有兴趣的话,可以关注一下专栏。
之前写了排序算法,和链表的基本操作和高端操作算法。接下来说说回溯法吧。其实这个是算法竞赛类的入门级别算法。虽然是入门级别的算法,但是你还别说,还是有很多人不会的。
我们今天用算法做一个全排列: 输入n,例如n=3 123 132 213 231 312 321
我们要做的是在屏幕上输出3的全排列。
这一题看起来好像很简单,但是没有学过算法的同学,还真不一定能做出来。 咋一看,可以用循环暴力做出来。 加入n固定是3的话,那就可以暴力3层循环就解决了这个问题 for(i=1;i<=3;i++) ... for(j=1;j<=3;j++) ... for(k=1;k<=3;k++) ...
然后这里的...就是要做剪枝操作,什么叫剪枝呢?这里拓展一下,那就是限制条件,把不满足的东西赛选出去。 很明显,我们的兼职条件是i!=j ,i!=k,j!=k。说白了就是ijk相互不能相等。看吧如何n固定是3的话是可以这样做的。
不过n并非是固定的,我们可以是4,可以是5,可以是100。那么我们不可能写不确层数的循环啊。所以我们这里需要用到递归。也就是自己调用自己。。
完整代码如下:
#include<iostream>
using namespace std;
int n,a[100],isUse[100];
//a数组用于保存每一次的排列,v数组用于判断数字是不是已经被选过
void dfs(int index)//index代表第几个数
{
if(index>n)//index为n+1的时候,就说明已经选了n个,可以输出了;
{
..完整代码,请移步到公众号:诗一样的代码
cout<<a[i]<<" ";
}
cout<<endl;
return;
}
for(int i=1;i<=n;i++)
{
if(!isUse[i])//判断是不是选择过
{
dfs(index+1);
isUse[i]=0;//回溯回来的时候一定要清楚标记,不然下一个排列就能选择了,这也是最关键的地方,仔细思考一下。
}
}
}
int main()
{
while(cin>>n)
{
dfs(1);
}
}
别小看这种算法,在很多情况下都是能用到的。有兴趣的可以做下下面这一题:
题解,可以关注公众号:诗一样的代码
既然进来了,原创不易。小伙伴点个赞再走呗。