<来源:HDU课件>
前言:
搜索算法是利用计算机的高性能来有目的地穷举一个问题的部分或所有的可能情况,从而求出问题的解的一种方法。
搜索过程实际上是根据初始条件和扩展规则构造一棵解答树并寻找符合目标状态的节点的过程。
题目:HDOJ,1010
DFS:
基本思想:从初始状态S开始,利用规则生成搜索树下一层任一个结点,检查是否出现目标状态G,若未出现,以此状态利用规则生成再下一层任一个结点,再检查是否为目标节点G,若未出现,继续以上操作过程,一直进行到叶节点(即不能再生成新状态节点),当它仍不是目标状态G时,回溯到上一层结果,取另一可能扩展搜索的分支。生成新状态节点。若仍不是目标状态,就按该分支一直扩展到叶节点,若仍不是目标,采用相同的回溯办法回退到上层节点,扩展可能的分支生成新状态,…,一直进行下去,直到找到目标状态G为止。
算法:
(1)把起始节点S线放到OPEN表中。
(2)如果OPEN是空表,则失败退出,否则继续。
(3)从OPEN表中取最前面的节点node移到CLOSED 表中。
(4)若node节点是叶结点(若没有后继节点),则转向(2)。
(5)扩展node的后继节点,产生全部后继节点,并把他们放在OPEN表的前面。各后继结点指针指向node节点。
(6)若后继节点中某一个是目标节点,则找到一个解,成功退出。否则转向(2)循环。
代码:
# include <iostream.h>
# include <string.h>
# include <stdlib.h>
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; //不在map内,坐标错误,回退
if(cnt==t&&si==di&&sj==dj) escape=1;//cnt时间计数,时间刚好时,刚好到达目的地,改变标志
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); //检查,注意cnt+1,而不能在if里面cnt++,因为要回溯,若采用cnt++,回溯时cnt不会减小
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++) //map中存放用1~n,不用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)
{
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;
}