这篇文大概就是自己在学习过程中学到的一些模板和注意事项吧,emmm在此先膜拜各路大佬orz
先贴核心代码:
void dfs()//参数用来表示状态
{
if(到达终点状态)
{
...//根据题意添加
return;
}
if(越界或者是不合法状态)
return;
if(特殊状态)//剪枝
return ;
for(扩展方式)
{
if(扩展方式所达到状态合法)
{
修改操作;//根据题意来添加
标记;
dfs();
(还原标记);
//是否还原标记根据题意
//如果加上(还原标记)就是 回溯法
}
要注意路径记录和节点重判!!!
然后接下来是一些最最最基础的dfs的题了,承蒙不弃QwQ
1.全排列
题目描述:
排列与组合是常用的数学方法。
先给一个正整数 ( 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
代码:
#include<stdio.h>
int n,a[1005];
int book[1005]={0};
void dfs(int m)
{
if (m == n)
{
for(int i = 0;i<n;i++)
{
printf("%d",a[i]);
if(i < n-1) printf(" ");
}printf("\n");
return ;
}
for (int i = 1;i <= n;i++)
{
if (book[i] == 1) continue ;
a[m] = i;
book[i] = 1;
dfs(m+1);
book[i] = 0;
}
}
int main()
{
scanf("%d",&n);
dfs(0);
return 0;
}
2,组合的输出
题目描述:
排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r < = n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。
现要求你不用递归的方法输出所有组合。
例如n = 5 ,r = 3 ,所有组合为:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
输入:
一行两个自然数n、r ( 1 < n < 21,1 < = r < = n )。
输出:
所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,所有的组合也按字典顺序。
代码如下:
#include<stdio.h>
int m[25],n,r;
void dfs(int a,int b)
{
if(a == r)
{for(int i = 0;i < r;i++) printf("%d ",m[i]);
printf("\n");}
if(r - a >n - b + 1) return ;
for(int i = b ;i <= n;i++)
{
m[a] = i; dfs(a+1,i+1);
}
}
int main()
{
scanf("%d %d",&n,&r);
dfs(0,1);
return 0;
}
先到此为止吧orz