深度優先搜索
深度優先搜索算法(英語: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;
}