深度优先搜索练习
题目一 : 全排列问题1
题目描述
输出自然数 1 到 n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
输入格式
一个整数 n。
输出格式
由 1 ∼ n 1 \sim n 1∼n 组成的所有不重复的数字序列,每行一个序列。
每个数字保留 5个场宽。
输入输出样例
输入 #1
3
输出 #1
1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
说明/提示
1 ≤ n ≤ 9 1\le n \le 9 1≤n≤9
//代码:
import java.util.Scanner;
public class Main{
static int n;
static int[] a = new int[10],book = new int[10];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
dfs(1);
}
public static void dfs(int step){
if (step > n){
for (int i = 1 ; i <= n ; i++ )
System.out.print(" "+a[i]);//场宽5
System.out.print("\n");
return;
}
for (int k = 1 ; k <= n ; k++ ) {
if (book[k] == 0) {
a[step] = k;
book[k] = 1;
dfs(step+1);
book[k] = 0;
}
}
return;
}
}
DFS入门题
题目二 : 八皇后2
题目描述
一个如下的 6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。
上面的布局可以用序列 2 4 6 1 3 5 来描述,第 i 个数字表示在第 i 行的相应位置有一个棋子,如下:
行号 1 2 3 4 5 6
列号 2 4 6 1 3 5
这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 3 个解。最后一行是解的总个数。输入格式
一行一个正整数 n,表示棋盘是 n×n 大小的。
输出格式
前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。
输入输出样例
输入 #1
6
输出 #1
2 4 6 1 3 5 3 6 2 5 1 4 4 1 5 2 6 3 4
说明/提示
【数据范围】对于 100% 的数据,6 ≤ n ≤ 13
//代码:
import java.util.Scanner;
public class Main{
static final int N = 100;
static int n,max,mark;
static int[] a = new int[N] , col = new int[N] , d = new int[N], ud = new int[N];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
dfs(1);
System.out.print(max);
}
public static void dfs(int step){
if (step > n) {
if (mark < 3) {
for (int i = 1 ; i <= n ; i++ ){
System.out.print(a[i]+" ");
}
mark++;
System.out.print("\n");
}
max++;
return;
}
for (int k = 1; k <= n ; k++) {
int t1 = step + k - 1;
int t2 = n + step - k;
if (col[k] == 0 && d[t1] == 0 && ud[t2] == 0) {
col[k] = d[t1] = ud[t2] = 1;
a[step] = k;
dfs(step+1);
col[k] = d[t1] = ud[t2] = 0;
}
}
}
}
经典题目
题目3 : 2n皇后问题3
题目描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出
输出一个整数,表示总共有多少种放法。
样例输入
4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
样例输出
2
//代码:
import java.util.Scanner;
public class Main{
static final int N = 20;
static int n , max = 0;
static int[][] book = new int[N][N];
static int[] col = new int[N] , di = new int[N] , ud = new int[N];
static int[] col2 = new int[N] , di2 = new int[N] , ud2 = new int[N];
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
for (int i = 1 ; i <= n ; i++)
for (int j = 1 ; j <= n ; j++ )
book[i][j] = scan.nextInt();
dfs(1);
System.out.println(max);
}
public static void dfs(int step){
if (step > n) {
dfs2(1);
return;
}
for (int k = 1 ; k <= n ; k++ ) {
int t1 = step + k - 1;
int t2 = n + step - k;
if ( book[step][k] == 1 && di[t1] == 0 && ud[t2] == 0 && col[k] == 0 ) {
book[step][k] = 0;
di[t1] = ud[t2] = col[k] = 1;
dfs(step+1);
book[step][k] = 1;
di[t1] = ud[t2] = col[k] = 0;
}
}
}
public static void dfs2(int step){
if (step > n) {
max++;
return;
}
for (int k = 1 ; k <= n ; k++ ) {
int t1 = step + k - 1;
int t2 = n + step - k;
if ( book[step][k] == 1 && di2[t1] == 0 && ud2[t2] == 0 && col2[k] == 0 ) {
book[step][k] = 0;
di2[t1] = ud2[t2] = col2[k] = 1;
dfs2(step+1);
book[step][k] = 1;
di2[t1] = ud2[t2] = col2[k] = 0;
}
}
}
}
n皇后问题的变种,使用二次dfs简化难度