深度优先DFS搜索算法

深度优先DFS搜索


什么是深度优先搜索?

深度优先搜索(DFS ,Depth-First Search)是搜索手段之一。它从某个状态,不断地转移状态直到无法转移,然后回退到前一步的状态,继续转移到其他状态,如此不断重复,直到找到最终的解。


如何实现深度优先搜索?


根据深度优先搜索的特点,采用递归函数实现比较简单。


算法实例


实例一:若干数和为k的问题。


题干:给定整数a1,a2......an。判断是否可以从中选出若干数,使他们的和为k(数不能加重复的)

限制条件:

1<=n<=20

-10^8<=ai<=10^8

-10^8<=k<=10^8

样例1:

输入:

n=4

a={1,2,4,7}

k=13

输出:

Yes(13=2+4+7)


样例二:

输入:

n=4

a={1,2,4,7}

k=15

输出:

No

分析:咋一看看确实很难实现:因为从a1开始按顺序决定每一个数加还是不加,这样一来每个数只有两种状态,加和不加。那么最终的算法复杂度就是O(2^n)。

只用普通的算法确实很难实现,但是用上递归问题就迎刃而解了。(ps:下面代码很不规范,命名尽量不要使用中文,我是为了自己好找到以前写的代码才这样做的)

完整代码如下:

package com.renyou.算法;

import java.util.Scanner;

public class 若干数的和为K递归问题 {
	private int n,k;
	private int[]a;
	public static void main(String[] args) {
        new 若干数的和为K递归问题().递归();
	}

	private void 递归() {
		Scanner scanner=new Scanner(System.in);
		k=scanner.nextInt();//若干数的和
		n=scanner.nextInt();//数的个数
		a=new int[n];
		for(int i=0;i<n;i++){
			a[i]=scanner.nextInt();
		}
		
		if(dfs(0,0)){
			System.out.println("yes");
		}else{
			System.out.println("no");
		}
	}

	private boolean dfs(int i, int sum) {
		if(i==n)return sum==k;
		
		if(dfs(i+1,sum))//不加上a[i]
			return true;
		if(dfs(i+1,sum+a[i]))//加上a[i]
			return true;
		return false;
	}
}

实例二:雨天积水数量问题。


题干:有一个大小为N*M的园子,雨后积水。八连通的积水被认为是连接在了一起。请求出园子里一共有多少水洼?

(八连通是指下图中相对*的w部分)

www

w*w

www

限制条件:

N,M<=100

输入:

N=5

M=5

园子如下图(w表示积水,*表示没有积水)

**w**

**w**

*****

***w*

**w**

输出:2

分析:

从任意的w开始,不停地把邻接的部分用‘*’代替。1次DFS后与初始的这个w连接的所有w就被替换成了*。因此知道图中没有w了,总共进行了几次的DFS就是积水的个数了。

8个方向对应8种状态转移,所以复杂度是O(8*N*m)=O(n^2)

完整代码如下:

package com.renyou.算法;

import java.util.Random;
import java.util.Scanner;

public class 积水个数的深度优先搜索DFS算法 {
	private char[][] field;
    private int width,height;
    
	public static void main(String[] args) {
		new 积水个数的深度优先搜索DFS算法().solve();
	}

	private void solve() {
		/************ 控制台输入数据 ********************/
		Scanner scanner = new Scanner(System.in);
		width = scanner.nextInt();
		height = scanner.nextInt();
		field = new char[width][height];
		/************* char数组赋值 ********************/
		Random random = new Random();
		int num;
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				num = random.nextInt(100);
				if (num % 5 == 0) {//因为输入太麻烦,自己随机生成
					field[i][j] = 'w';
				} else {
					field[i][j] = '.';
				}
			}
		}
		/************ 自动生成field数组元素 *********************/
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				System.out.print(field[i][j]);
			}
			System.out.println();
		}
		
		
		/********* 开始遍历计算field *********/
		int res = 0;
		for (int i = 0; i < width; i++) {
			for (int j = 0; j < height; j++) {
				if (field[i][j] == 'w') {
					dfs(i, j);
					res++;
				}
			}
		}
		System.out.println("积水个数" + res);
	}

	private void dfs(int i, int j) {
		field[i][j] = '.';//很重要
		for (int dx = -1; dx <= 1; dx++) {
			for (int dy = -1; dy <= 1; dy++) {
                 int nx=i+dx;
                 int ny=j+dy;
                 //如果在field内并且有积水继续深度搜索
                 if(nx>=0&&nx<width&&ny>=0&&ny<height&&field[nx][ny]=='w'){
                	 dfs(nx,ny);
                 }
			}
		}
	}

}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值