问题:P1706 全排列问题
刚开始学DFS的时候,我也感觉很迷惑,不知道它的来龙去脉,刷了些题之后也是感觉懵懵懂懂的,只能尝试套模版,但随着学习的深入,学了BFS,背包问题等更复杂的算法之后终于对搜索有了更全面的认识。如果你和我之前一样对搜索感到迷惑的话,千万不要放弃,争取每次理解一点,随着学习的深入,一定会慢慢体会到它的精髓的。加油,朋友!
我们可以把它当成把1-n的扑克牌放到n个小盒子的过程。整个的求解过程就是一个搜索过程,依次尝试每一种可能,最外层一个for()循环来枚举1号位置,然后再自身调用自己的for()循环来枚举2号,然后在自身调用自己的for循环来枚举3号,依次类推。
举例:当n==3时
1号盒可能的情况1(2,3),然后枚举2号可能的情况2(3),最后3号盒只能放3(第一种123),回到2号盒,尝试剩余的3号,到了3号和,只能放2号(第二种132),现在2号盒和3号盒都枚举完了。
1号盒枚举2号(3),然后枚举2号盒可能的情况1(3),到了3号盒只放3(第三种213),回到2号盒枚举剩余的3,来到3号盒只能放1(第四种231),
1号盒剩余的3,然后枚举2号盒可能的情况1(2)到了3号盒只能放2(第五种312),然后回到2号盒尝试剩余的2,到了3号盒只有1(第六种321)
其实搜索的过程就是枚举的过程,也是搜索的过程,对每一个可能的路径搜索到不能深入为止,而且每个节点只访问一次。实现如下:
#include <stdio.h>
int n,book[100000],a[100000]; //book记录该点是否放过 a记录排列情况
void dfs(int step){
if(step==n+1){ //当走到盒子外的时候说明已经完成了一次全排列,输出
for(int i=1;i<=n;i++)
printf("%5d",a[i]);
printf("\n");
return ; //回到前一个盒子
}
for(int i=1;i<=n;i++){
if(!book[i]) { //判断该点是否有数字
a[step]=i; //放入数字
book[i]=1; //记录
dfs(step+1); //尝试下一个盒子的可能情况
book[i]=0; //收回该盒子的数字
}
}
}
int main() {
scanf("%d",&n);
dfs(1); //搜素从1号盒开始
return 0;
}
建议题目:E - 迷宫问题
参考资料:百度百科——深度优先搜索