欢迎来我的个人博客浏览这篇文章哦~(还有背景音乐可以听!)点这里!
BFS与DFS一样搜索n阶幻方的时间复杂度至少为O(n!),并且由于控制搜索状态的队列要储存每一个状态(state)节点,并且搜索幻方的数据规模较大,很容易造成内存溢出,当我在vscode中运行搜索四阶幻方时就发生了堆内存溢出(Java heap space),由此可见,用BFS求n阶幻方比DFS更加不现实。
状态节点state类的定义如下:
public class state {
// 幻方容器
int[] matrix;
// 记录当前幻方中已经使用的数字
boolean[] used;
// 结点深度
int deep;
// 幻方的阶数
int grade;
// 构造函数
state(int grade) {
this.grade = grade;
matrix = new int[grade * grade + 1];
used = new boolean[grade * grade + 1];
deep = 0;
}
// 遍历输出
void Traverse() {
System.out.println("幻方:");
for (int i = 0; i < grade; ++i) {
for (int j = 1; j <= grade; ++j) {
System.out.print(matrix[i * grade + j] + " ");
}
System.out.println();
}
}
}
幻方类与测试main函数代码如下:
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Scanner;
public class MagicSquareBFS {
// 幻方的阶数
int grade;
// 幻方每行(列、对角线)上的数字之和
int key;
// 计算程序运行时间所需变量
static long stime = System.currentTimeMillis();
static long etime;
// 构造函数
MagicSquareBFS(int grade) {
this.grade = grade;
// 计算幻方每行(列、对角线)上的数字之和
int sum = 0;
for (int i = 1; i <= grade * grade; ++i) {
sum += i;
}
key = sum / grade;
}
// 广度优先搜索
state bfs() {
Queue<state> queue = new ArrayDeque<>();
state a = new state(grade);
a.deep = 1;
queue.offer(a);
while (!queue.isEmpty()) {
state first = queue.poll();
for (int i = 1; i <= grade * grade; ++i) {
if (first.used[i] == false) {
state b = new state(grade);
b.deep = first.deep;
System.arraycopy(first.matrix, 0, b.matrix, 0, first.matrix.length);
System.arraycopy(first.used, 0, b.used, 0, first.matrix.length);
b.used[i] = true;
b.matrix[b.deep++] = i;
if (judge(b.matrix, b.deep)) {
return b;
} else {
queue.offer(b);
}
}
}
}
return a;
}
// 判断是否为幻方
boolean judge(int[] matrix, int deep) {
if (deep == grade * grade + 1) {
// 检查每行每列
if (!checkRowsAndColumns(matrix)) {
return false;
}
// 检查主副对角线
if (!checkDiagonals(matrix)) {
return false;
}
return true;
}
return false;
}
// 检查每行每列
boolean checkRowsAndColumns(int[] matrix) {
for (int i = 0; i < grade; ++i) {
int rowSum = 0;
int colSum = 0;
for (int j = 0; j < grade; ++j) {
rowSum += matrix[(i * grade) + j + 1];
colSum += matrix[(j * grade) + i + 1];
}
if (rowSum != key || colSum != key) {
return false;
}
}
return true;
}
// 检查主副对角线
boolean checkDiagonals(int[] matrix) {
int mainDiagonalSum = 0;
int subDiagonalSum = 0;
for (int i = 1; i <= grade * grade; i += grade + 1) {
mainDiagonalSum += matrix[i];
}
for (int i = grade * grade - grade + 1; i >= grade; i = i - grade + 1) {
subDiagonalSum += matrix[i];
}
if (mainDiagonalSum != key || subDiagonalSum != key) {
return false;
}
return true;
}
// main函数
public static void main(String[] args) {
System.out.println("输入幻方的阶数:");
Scanner sc = new Scanner(System.in);
int grade = sc.nextInt();
sc.close();
MagicSquareBFS square = new MagicSquareBFS(grade);
square.bfs().Traverse();
etime = System.currentTimeMillis();
System.out.println("程序共运行" + (etime - stime) / 1000 + "秒");
}
}