全排列问题
问题描述
按照字典序输出自然数 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);
}
}
}
}