问题描述
在N×N的棋盘上摆放N个皇后,使其不能互相攻击,即任意的两个皇后不能处在同一行,同一列,或同一斜线上。请输出对于N有多少种摆放。
输入描述:
输入N,棋盘则为N×N, 棋盘上摆N个皇后。
例如:N=4, 则棋盘为4×4,棋盘上摆4个皇后.
输出描述:
输出格式为:
Total count: M
M代表对于输入N,总共有多少种摆放。
解题思路
使用栈(Stack)来模拟深度优先搜索(DFS)过程,以求解N皇后问题。
1.初始化
- 定义一个计数器count来记录找到的总解数。
- 定义一个栈stack来保存搜索过程中的状态。
- 定义一个自定义的栈帧类Frame,用于保存当前棋盘状态的信息(棋盘大小n、当前正在处理的行row、以及皇后列位置数组queens)。
2.读取输入
使用Scanner读取用户输入的棋盘大小N。
3.开始搜索
初始化一个长度为N的整数数组queens,用于记录每一行皇后的列位置。
将初始状态(row = 0,queens数组为空)封装为一个Frame对象,并压入栈中。
4.栈不为空时循环
从栈中弹出一个Frame对象,即当前搜索状态。
如果当前状态对应的行号row等于棋盘大小n,说明已经成功放置了所有皇后,找到一个解,增加计数器count的值。
否则,遍历当前行的每一列col:
检查在(row, col)位置放置皇后是否安全(即是否与其他皇后冲突)。
如果安全,则在queens数组中标记该位置,并创建一个新的Frame对象(表示下一行的状态),将其压入栈中。
5.回溯
如果在当前行的所有列都尝试放置过皇后,但没有找到安全的位置,则需要回溯,即将当前行的状态撤销(即在栈中弹出当前状态),并尝试上一行的下一个位置。
6.输出解的总数
当栈为空时,表示已经搜索完所有可能的状态,此时输出找到的总解数。
Java代码实现
import java.util.Scanner;
import java.util.Stack;
public class Main
{
// 计数器,用于记录找到的总解数
private static int count = 0;
// 自定义的栈帧类,用于保存状态
static class Frame
{
// 棋盘的大小
int n;
// 当前正在处理的行
int row;
// 用来存储每一行皇后的列位置的数组
int[] queens;
// 构造函数,用于初始化栈帧
Frame(int n, int row, int[] queens)
{
this.n = n;
this.row = row;
this.queens = queens;
}
}
public static void main(String[] args)
{
// 读取用户输入的N值
Scanner in = new Scanner(System.in);
while (in.hasNextInt())
{
int N = in.nextInt(); // 获取输入的N值
int[] queens = new int[N]; // 初始化皇后的列位置数组
// 创建一个栈来保存状态
Stack<Frame> stack = new Stack<>();
// 初始状态,第一行尚未放置皇后
stack.push(new Frame(N, 0, queens));
// 当栈不为空时,继续处理
while (!stack.isEmpty())
{
Frame frame = stack.pop(); // 弹出栈顶状态
// 如果已经处理完所有行,则找到一个解
if (frame.row == frame.n)
{
count++; // 解数加一
}
else
{
// 遍历当前行的所有列
for (int col = 0; col < frame.n; col++)
{
// 检查在(row, col)位置放置皇后是否安全
if (isValid(frame.n, frame.queens, frame.row, col))
{
// 放置皇后
frame.queens[frame.row] = col;
// 创建新的状态(下一行),并压入栈中
stack.push(new Frame(frame.n, frame.row + 1, frame.queens.clone()));
}
}
}
}
// 输出N皇后问题的解的总数
System.out.println("Total count: " + count);
count = 0; // 重置计数器以便处理下一个输入
}
in.close(); // 关闭输入流
}
// 检查在(row, col)位置放置皇后是否安全
private static boolean isValid(int n, int[] queens, int row, int col)
{
// 检查列上是否有皇后互相攻击
for (int i = 0; i < row; i++)
{
if (queens[i] == col)
{
return false;
}
}
// 检查左上方对角线上是否有皇后互相攻击
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--)
{
if (queens[i] == j)
{
return false;
}
}
// 检查右上方对角线上是否有皇后互相攻击
for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++)
{
if (queens[i] == j)
{
return false;
}
}
// 所有检查都通过,可以安全放置皇后
return true;
}
}