深度优先搜索(dfs)

全排列问题

问题描述
按照字典序输出自然数 1 到 n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
P1706 全排列问题

解题思路
dfs+回溯。
在这里插入图片描述
完整代码

import java.util.Scanner;

public class Main { //80
	static int n;
	static int[] a=new int[10];
	static int[] vis=new int[10];
	
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		dfs(1);
	}
	
	static void dfs(int k) {
		if(k>n) {
			for (int i = 1; i <=n; i++) {
				System.out.printf("%5d",a[i]);
			}
			System.out.println();
		}
		for (int i = 1; i <= n; i++) {
			if(vis[i]==0) {
				a[k]=i;
				vis[i]=1;
				dfs(k+1);
				vis[i]=0; //回溯
			}
		}
	}
}

八皇后问题

问题描述
一个如下的 6×6 的棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
P1219 八皇后

解题思路
dfs+回溯。
在这里插入图片描述
完整代码

import java.util.Scanner;

public class Main {
	static int n;
	static boolean[] lie=new boolean[14]; //列
	static boolean[] u=new boolean[28]; //左上到右下
	static boolean[] v=new boolean[28]; //右上到左下
	static int[] a=new int[14];
	static int count;
	
	static void dfs(int x) {
		if(x>n) {
			count++;
			if(count<=3) {
				for (int i = 1; i <= n; i++) {
					System.out.print(a[i]+" ");
				}
				System.out.println();
			}
			return;
		}
		for (int i = 1; i <= n; i++) {
			if(!lie[i] && !u[x-i+n] && !v[x+i]) {
				lie[i]=true;
				u[x-i+n]=true;
				v[x+i]=true;
				a[x]=i;
				dfs(x+1);
				lie[i]=false;
				u[x-i+n]=false;
				v[x+i]=false;
			}
		}
	}
	
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		dfs(1);
		System.out.println(count);
	}
}

全球变暖

问题描述
你有一张某海域NxN像素的照片,".“表示海洋、”#"表示陆地,如下所示:


.##…
.##…
…##.
…####.
…###.

其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有2座岛屿。

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

例如上图中的海域未来会变成如下样子:





…#…

请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

蓝桥杯-全球变暖

解题思路
dfs+连通块,对于该题,如果某块陆地的邻海像素个数和等于总像素和,则该陆地就会被完全淹没。

完整代码

import java.util.Scanner;

public class 全球变暖 {  //蓝桥官网 87分
	static int n;
	static char[][] a=new char[1000][1000];
	static boolean[][] vis=new boolean[1000][1000];
	static int[] dx = new int[] {1,0,-1,0};
	static int[] dy = new int[] {0,1,0,-1};
	static int sland,land; //邻海陆地块,陆地块数量
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		
		for(int i=0;i<n;i++) {
			a[i] = sc.next().toCharArray();
		}
		
		//疑问:这里存在淹没后,一块陆地变成两块陆地的情况,
		//因此 先前陆地数量-淹没后剩余陆地数量 的思路是错误的
		int ans=0;
		for(int i=0;i<n;i++) {
			for(int j=0;j<n;j++) {
				if(a[i][j]=='#' && !vis[i][j]) {
					sland=land=0;
					vis[i][j]=true;
					dfs(i,j);
					if(sland==land) ans++;
				}	
			}
		}
	
		System.out.println(ans);
	}
 
	static boolean is(int x,int y) {
		for(int i=0;i<4;i++) {
			int tx=x+dx[i];
			int ty=y+dy[i];
			if(tx>=0 && tx<n && ty>=0 && ty<n && a[tx][ty]=='.') {
				return true;
			}
		}	
		return false;
	}
	
	static void dfs(int x,int y) {
		land++;
		if(is(x,y)) sland++;
		
		for(int i=0;i<4;i++) {
			int tx=x+dx[i];
			int ty=y+dy[i];
			if(tx>=0 && tx<n && ty>=0 && ty<n && a[tx][ty]=='#' && !vis[tx][ty]) {
				vis[tx][ty]=true;
				dfs(tx,ty);
			}
		}
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值