深度优先搜索学习五例之四(JAVA)

先继续“深度优先搜索学习五例之三”[url]http://128kj.iteye.com/admin/blogs/1702286[/url]中的迷宫,那里用栈实现了深搜,但只输出了一条路径,下面程序用递归实现深搜,输出所有到出口的路径和数目:
import java.util.Stack;   

//深度优先搜索之迷宫问题:输出所有到出口的路径
public class MazeDsf{
private static final int M=9;
private static final int N=8;
private int total;

//迷宫矩阵,0为通道,1为障碍
//入口(0,0),出口(8,7)
private int[][] Matrix = {
{ 0, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 1, 0, 1, 0 },
{ 0, 0, 0, 0, 0, 0, 1, 0 },
{ 0, 1, 0, 0, 0, 0, 1, 0 },
{ 0, 1, 0, 1, 1, 0, 1, 0 },
{ 0, 1, 0, 0, 0, 0, 1, 1 },
{ 0, 1, 0, 0, 1, 0, 0, 0 },
{ 0, 1, 1, 1, 1, 1, 0, 0 } };


public MazeDsf(){
total=0;
}


//右下上左
private int x_off[] = {0,1,-1,0};
private int y_off[] = {1,0,0,-1};


//输出迷宫
private void PrintMatrix(){
System.out.println("入口(0,0),出口(8,7)的迷宫,2为通道,1为障碍:");
for(int i = 0; i < M; ++i){
for(int j = 0; j < N; ++j)
System.out.print(Matrix[i][j]);
System.out.println();
}
}
//深度优先搜索所有可能的路径
public void dfs(int x,int y)
{
Matrix[x][y]=2;
if(x == 8&& y == 7){
//输出找到的路径
total++;
PrintMatrix();

}

for(int i = 0; i<4; ++i){ //右下上左
int nx = x + x_off[i];
int ny = y + y_off[i];
if(nx >= 0 && nx < M && ny>=0 && ny< N && Matrix[nx][ny] == 0){
dfs(nx,ny);
}
}
Matrix[x][y] =0;//这里就是回溯,很重要!!!
}

public int getTotal(){
return total;
}


//测试代码主函数
public static void main(String args[]) {
MazeDsf maze=new MazeDsf();
maze.PrintMatrix();
maze.dfs(0,0);
System.out.print("共有"+maze.getTotal()+"条路径");
}
}


运行结果:
.........................................省略很多
入口(0,0),出口(8,7)的迷宫,2为通道,1为障碍:
21111111
20000000
21111010
22202210
01222210
01011210
01000211
01001222
01111102
入口(0,0),出口(8,7)的迷宫,2为通道,1为障碍:
21111111
20000000
21111010
22202210
01222210
01011210
01000211
01001220
01111122
.......................
共有72条路径

再看下面POJ1562:
题意:在一个n*m的地图上探索有多少块油田,'@'表示单位油田,相邻的(上下左右与对角线)单位油田为一个大油田,问有多少个大油田。

Sample Input

1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0
Sample Output

0
1
2
2

就是求多少个连通分量,顺序扫描,每扫面到一个@,并且这个格子没有被深度遍历过,就进行一次深度优先遍历.

import java.util.Scanner;
public class Main{
int m, n;
char map[][];
int move[][] = { {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} };

public Main(int m,int n,char[][] map){
this.m=m;
this.n=n;
this.map=map;

}

private void DFS(int si, int sj) {


for (int i = 0; i<8; ++i) {
int mi = si + move[i][0];
int mj = sj + move[i][1];
if (mi >= m|| mj >= n || mi < 0 ||mj < 0) continue ;
if (map[mi][mj] == '@') {
map[mi][mj] = '*';
DFS(mi, mj);
}
}
return ;
}

public static void main(String args[]){
Scanner in=new Scanner(System.in);
while(true){
int a=in.nextInt();
int b=in.nextInt();
if(a==0&&b==0)break;
int count=0;
char[][] map=new char[a][b];
for(int i=0;i<a;i++){
String s=in.next();
for(int j=0;j<b;j++)
map[i][j]=s.charAt(j);
}
Main m=new Main(a,b,map);
int answer=0;
for (int i = 0; i<a; i++)
for (int j = 0; j<b; j++)
if (map[i][j] == '@') {
map[i][j] = '*';
m.DFS(i, j);
++answer;
}


System.out.printf("%d\n", answer);
}
}
}


下载:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值