在网上找到了一个神奇的网站。算法笔记
DFS是一种十分重要也中用的算法。
对于大多数问题,只要用了DFS,都可以解决。
以下是我总结出来的关于它的一些思想。
这是一个十分重要的框架,但只能重复搜索。
Type solution[MAXN]; //保存解的数组
void dfs(int i) { //当前搜索第i个阶段
if (到达边界)
{
检验solution是否是合法解;
记录解或者输出解;
return;
}
for (第i个阶段的所有选项)
if (j是合法选项)
{
solution[i] = j; //保存当前选项;
dfs(i+1); //递归到下一阶段
}
}
下列是两种对上面问题的解决方法,但只能针对答案不重复。
函数法
bool check(int i,int j)//判断此元素在当前答案里是否重复
{
for(int k=0;k<i;k++)
if(ans[k]==j)return 0;
return 0;
}
for(int j=1;j<=k;j++)
if(check(i,j))
{
ans[i]=j;
dfs(i+1);
}
数组法(非常实用)
int vis[];
void dfs(int x)
{
if(超出范围)
return 0;
for(枚举所有元素)
if(!vis[j])
{
vis[i]=1;ans[x]=j
dfs(x+1);
vis[i]=0;//回溯
}
}
对于重复元素的排列。
数组法是一个实用的方法:把元素数量存下来,再判断是否超出。
而数组在对于大多数参数都能找出并判断。
而记忆化搜索就是建立在数组法的基础上的。
只需判断一下价值大小就可以了。例题
最后,介绍一个关于排列的函数。
#include<cstdio>
#include<algorithm>
using namespace std;//调用STL函数
#define M 10
int a[M],cnt;
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);//生成最小排列(从小到大排序)
do
{
printf("%d:",++cnt);
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\n",a[n]);
}while(next_permutation(a+1,a+1+n));
return 0;
}