广度遍历的代码如下:
private void bfs(int i, boolean[] visited){
Queue q=new SequenceQueue();
System.out.print(i+" ");
visited[i]=true;
q.enter(i);
while(!q.isEmpty()){
int k=(Integer)q.leave();
for(int j=0; j<n; j++){
if(a[k][j]!=0 && a[k][j]!=MaxValue && !visited[j])
{
System.out.print(j+" ");
visited[j]=true;
q.enter(j);
}
}
}
}
我们在进行广度遍历时需要检验节点是不是走过,并且从广度遍历的方式我们也可以得出 在通过广度遍历找到到点a的路径时,这个路径就是最短路径。
例题一:抓住那头牛
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(
0<=N<=100000)。农夫有两种移动方式:1,从x移动到x-1或者x+1,每次移动花费一分钟 2.从x移动到2*x,每次移动花费一分钟,假设牛没有意识到农夫的行动,站在原地不动。农夫最少花多少时间才能抓住牛?
(假设农夫在点3,牛位于点5)
思考:从农夫的起点开始有多种走法,并且我们要花最少的时间其实就是利用广度遍历找到从N点到K点的路径,可以在纸上将所有可能的路径画出来。 代码如下:深度搜索
public class lian {
public void jisuan(int a[][],int n,int visited[],String str) {
if(n==5) {
System.out.print(str);
return;
}
for(int i=0;i<7;i++) {
if(a[n][i]!=0&&visited[i]==0) {
visited[i]=1;
jisuan(a,i,visited,str+n+"到"+i+" ");
visited[i]=0;
}
}
}
public static void main(String[] args) {
lian b=new lian();
int a[][]=new int[7][7];
int visited[]= {0,0,0,0,0,0,0};
a[0][1]=a[1][0]=1;
a[2][4]=1;
a[1][2]=a[2][1]=1;
a[3][4]=a[4][3]=1;
a[2][3]=a[3][2]=1;
a[3][6]=1;
a[4][5]=a[5][4]=1;
a[5][6]=a[6][5]=1;
b.jisuan(a,3,visited," ");
}
}
广度优先搜索:
例题二:迷宫问题 定义一个矩阵 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或者竖着走,不能斜着走,要求编程求出从左上角到右下角的最短路线。
思考:这个题的状态是(x,y)这是一个基础广搜问题。先将起始位置放入队列,每次从队列中拿出一个元素,扩展其相邻的4个元素入队列(要判重),直到队头元素为终点为止。队列里的元素记录了指向父节点(上一步)的指针。此时队列要用我们自己写的,因为此时队列出栈一个元素后,不能将其删除 扩展问题:鸣人和佐助
用二维矩阵表示一张地图,已知鸣人和佐助的位置,地图上每个位置都可以走,只不过有些位置上有大蛇丸的手下,鸣人需要打败这些手下才能走到这些位置。鸣人有一定数目的查克拉,每一单位的查克拉都可以打败一个大蛇丸的手下,假设鸣人可以上下左右走,且花费时间相同,如果鸣人查克拉用完,则只可以移动到没有大蛇丸手下的位置。佐助和大蛇丸的手下在此期间不能移动,问鸣人追上佐助的最少时间是? 思考:这时我们的状态应该定义为(r,c,k)鸣人所在的行,列和查克拉数量
扩展问题:求钥匙的鸣人 佐助被关在一个格子里,需要集齐k种钥匙才能打开格子里的门救出他。k种钥匙散落在迷宫里。有的格子里放有一把钥匙。一个格子最多放一把钥匙,走到放钥匙的格子,即得到钥匙,问鸣人最少走多少步才能救出佐助
思考:这时的状态应该是(r,c,keys) 鸣人的行,列和已经拥有的钥匙种数 目标状态是(x,y,k) (x,y)是佐助呆的地方
如果队头节点扩展出来的节点上面拥有不曾拥有的某种钥匙,则该节点的keys比队头节点的keys要加1