深度优先搜索
深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。
有一点感觉很有趣,因发明“深度优先搜索算法”,约翰·霍普克洛夫特与罗伯特·塔扬在1986年共同获得计算机领域的最高奖:图灵奖。
八皇后问题
经典的dfs入门题
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=12;
int map[maxn][maxn];
int ans,n;
int ans_arr[maxn];
void dfs(int ithqueue);
int main()
{
for(n=1;n<maxn;++n) //n代表几皇后
{
ans=0;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)map[i][j]=0;
}
dfs(1); //从第一个开始放
ans_arr[n]=ans;
}
int q;
while(~scanf("%d",&q),q){
printf("%d\n",ans_arr[q]);
}
return 0;
}
void dfs(int ithqueue){ //ithqueue代表当前放了第几个
if(ithqueue==n+1){ //如果放到了第n+1个,代表放完了。
ans++;
return ;
}
for(int col=1;col<=n;++col) //很明显第几个皇后代表第几行,col从1到n开始扫描,代表将当下的皇后放到第几列
{
if(map[ithqueue][col]==0) //等于0,代表可以放
{
for(int i=1;i<=n;++i) //如果该行该列该斜线还是0的话则标记
{
for(int j=1;j<=n;++j)
{
if(( i==ithqueue || col==j || abs(i-ithqueue)==abs(col-j) ) && map[i][j]==0)
{
map[i][j]=ithqueue;
}
}
}
dfs(ithqueue+1); //放下一个皇后
for(int i=1;i<=n;++i) //回溯
{
for(int j=1;j<=n;++j)
{
if(map[i][j]==ithqueue) map[i][j]=0;
}
}
}
}
}
质数环问题
通过深搜实现全排列1
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
//queue<int> a; //本来想开队列保存答案,感觉这样会超时
int arr[21]; //用来标记是否已经放过改数字
int cir[21]; //保存答案
int num,h,flag,T=1;
void dfs(int n);
int isPrime(int n);
int main()
{
while(~scanf("%d",&num))
{
for(int i=0;i<20;i++) arr[i]=1;
flag=1;
cir[1]=1; //将1先置于环内
arr[1]=0; //1已经用过了
dfs(2); //放第二个数
printf("\n");
}
return 0;
}
void dfs(int n){
if(flag)
{
printf("Case %d:\n",T);
flag=0;
T++;
}
if(n==num+1)
{ //放满了,退出
if(isPrime(1+cir[num]))
{
for(int i=1;i<num;++i)
{
printf("%d ",cir[i]);
}
printf("%d\n",cir[num]);
}
return ;
}
int i;
for(i=2;i<=num;i++) //一遍一遍的扫描下一个要放置的数。
{
if(arr[i]==1 && isPrime(i+cir[n-1]) )//如果这个数没有被放过,并且这个数和之前放进的数相加等于质数,则放进该数。
{
arr[i]=0; //这个数已经用过
h=i;
cir[n]=i; //将i这个数放进环里
dfs(n+1); //开始放置下一个数
arr[i]=1; //回溯
}
}
if(i==num+1) return ; //后面的数怎么放都不行了,结束。
}
int isPrime(int n)
{
int i,k;
k=sqrt(n);
for(i=2;i<=k;i++)
{
if(n%i==0) break;
}
if(i<=k) return 0;
else return 1;
}
网易:最小众倍数
通过深搜实现全排列2
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int num[5];
int vis[5];
int stc[3];
int top;
int maxn=1<<30;
int ans;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int lcm(int a,int b,int c)
{
int lcm1=a*b/gcd(a,b);
int lcm2=lcm1*c/gcd(lcm1,c);
return lcm2;
}
int dfs(int ith)
{
if(ith==4)
{
//cout<<stc[0]<<" "<<stc[1]<<" "<<stc[2]<<endl;
//cout<<lcm(stc[0],stc[1],stc[2])<<endl;
if(lcm(stc[0],stc[1],stc[2])<ans)
{
ans=lcm(stc[0],stc[1],stc[2]);
}
return 0;
}
for(int i=0;i<5;++i)
{
if(!vis[i])
{
vis[i]=1;
stc[top++]=num[i];
dfs(ith+1);
vis[i]=0;
top--;
}
}
return 0;
}
int main()
{
while(cin>>num[0]>>num[1]>>num[2]>>num[3]>>num[4])
{
memset(vis,0,sizeof(vis));
top=0;
ans=maxn;
dfs(1);
cout<<ans<<endl;
}
return 0;
}