2.搜索策略:
深度優先遍歷圖的方法是,從圖中某頂點v出發:
(1)訪問頂點v;
(2)依次從v的未被訪問的鄰接點出發,對圖進行深度優先遍歷;
直至圖中和v有路徑相通的頂點都被訪問;
(3)若此時圖中尚有頂點未被訪問,則從一個未被訪問的頂點出發,
重新進行深度優先遍歷,直到圖中所有頂點均被訪問過爲止。
3.搜索僞代碼:
DFS(Node)
{
if(Node==目標節點)
then//找到目標,return
for each-next∈d[Node]
doDFS(next);
end
}
當然一般情況下的DFS算法的實現會用到數據結構-棧,也可以使用遞歸來實現,但是效率額偏低,所以要注意剪枝(就是提前排除不可能的情況)。
4.具體題目:
http://acm.hdu.edu.cn/showproblem.php?pid=1016 質數環
//簡單的DFS 不用剪枝,也可以A
//Time:890MS
//Mem :376K
#include <iostream>
#include <cstring>
using namespace std;
int ring[25];
int visited[25];
int n;
int isPrime(int p)
{
if(p==1 || p==2 || p==3 || p==5 || p==7 || p==11 || p==13 || p==17 || p==19
|| p==23 || p==29 || p==31 ||p==37 || p==41 || p == 43)
return 1;
else
return 0;
}
void dfs(int dep)
{
if(dep == n)//跳出遞歸的條件。
{
if( isPrime(ring[n-1] + 1) )
{
for(int i=0; i<n-1; i++)
cout<<ring[i]<<" ";
cout<<ring[n-1]<<endl;
return;
}
}
for(int i=2; i<=n; i++)
{
if(!visited[i] && isPrime(ring[dep-1]+i) )
{
visited[i] = 1;
ring[dep] = i;
dfs(dep+1);
visited[i] = 0;
}
}
return;
}
int main()
{
int test=0;
while(cin>>n)
{
memset(ring, 0, sizeof(ring));
memset(visited, 0, sizeof(visited));
visited[1] = 1;
ring[0] = 1;
cout<<"Case "<<++test<<":\n";
dfs(1);
cout<<endl;
}
return 0;
}
http://acm.hdu.edu.cn/showproblem.php?pid=1010 走迷宮(典型的DFS)
/*
這個題目的剪枝思路如下:
可以把迷宮看成這樣:
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
1 0 1 0 1 0
0 1 0 1 0 1
從爲 0 的格子走一步,必然走向爲 1 的格子
從爲 1 的格子走一步,必然走向爲 0 的格子
即:
0->1或1->0 必然是奇數步
0->0 走1->1 必然是偶數步
所以:所以當遇到從 0 走向 0 但是要求時間是奇數的,或者, 從 1 走向 0 但是要求時間是偶數的 都可以直接判斷不可達!
*/
//Time:62MS
//Mem :364K
#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
char map[9][9];
int n,m,t,di,dj;
bool escape;
int dir[4][2]={{0,-1},{0,1},{1,0},{-1,0}}; //表示四個方向。
void dfs(int si,int sj,int cnt)
{
int i,temp;
if(si>n || sj>m || si<=0 || sj<=0)
return;
if(cnt==t && si==di && sj==dj)
escape=1;
if(escape)
return;
temp = (t-cnt) - abs(si-di) - abs(sj-dj); //奇偶剪枝
if(temp<0 || temp&1)//如果爲奇數。
return;
for(i=0;i<4;i++)
{
if(map[si+dir[i][0]][sj+dir[i][1]]!='X')
{
map[si+dir[i][0]][sj+dir[i][1]]='X';
dfs(si+dir[i][0],sj+dir[i][1],cnt+1); //使用遞歸實現棧。
map[si+dir[i][0]][sj+dir[i][1]]='.';
}
}
return;
}
int main()
{
int i,j,si,sj;
while(cin>>n>>m>>t)
{
if(n==0 && m==0 && t==0)
break;
int wall=0;
for(i=1; i<=n; i++) //i=0j=0的情況爲牆。
for(j=1; j<=m; j++)
{
cin>>map[i][j];
if(map[i][j]=='S') { si=i; sj=j; } //開始地
else if(map[i][j]=='D') { di=i; dj=j; } //目的地
else if(map[i][j]=='X') wall++; //牆的數目
}
if(n*m-wall<=t)// n*m - t包括s和d節點。
{
cout<<"NO"<<endl;
continue;
}
escape=0;
map[si][sj]='X';
dfs(si,sj,0);
if(escape)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}