欢迎来我的个人博客浏览这篇文章哦~(还有背景音乐可以听!)点这里!
由于DFS是全遍历的、无信息的暴力搜索,所以该算法的时间复杂度为n阶矩阵的所有可能排列情况,也就是O(n!),其中n为矩阵的阶数。
由于搜索时间过长,我花了四十五分钟才跑出来四阶幻方的一个解,所以用DFS解n阶幻方是完全不现实的。
幻方类与测试的main函数代码如下:
import java.util.Scanner;
public class MagicSquareDFS {
// 幻方的阶数
int grade;
// 幻方每行(列、对角线)上的数字之和
int key;
// 记录当前幻方中已经使用的数字
boolean[] used;
// 幻方容器
int[][] square;
// 计算程序运行时间所需变量
static long stime = System.currentTimeMillis();
static long etime;
// 构造函数
MagicSquareDFS(int grade) {
this.grade = grade;
used = new boolean[grade * grade + 1];
square = new int[grade][grade];
// 计算幻方每行(列、对角线)上的数字之和
int sum = 0;
for (int i = 1; i <= grade * grade; ++i) {
sum += i;
}
key = sum / grade;
}
// 判断是否为幻方
void judge() {
// 检查每行每列
for (int i = 0; i < grade; ++i) {
int sum = 0;
for (int k = 0; k < grade; ++k) {
sum += square[i][k];
}
if (sum != key) {
return;
}
sum = 0;
for (int k = 0; k < grade; ++k) {
sum += square[k][i];
}
if (sum != key) {
return;
}
}
// 检查主副对角线
int sum = 0;
for (int k = 0; k < grade; ++k) {
sum += square[k][k];
}
if (sum != key) {
return;
}
sum = 0;
for (int k = 0; k < grade; ++k) {
sum += square[k][grade - k - 1];
}
if (sum != key) {
return;
}
// 输出结果
Traverse();
etime = System.currentTimeMillis();
System.out.println("程序共运行" + (etime - stime) / 1000 + "秒");
System.exit(1);
}
// 遍历幻方
void Traverse() {
System.out.println("幻方:");
for (int i = 0; i < grade; ++i) {
for (int j = 0; j < grade; ++j) {
System.out.print(square[i][j] + " ");
}
System.out.println();
}
}
// 深度优先搜索
public void dfs(int n) {
// 幻方被填满
if (grade * grade == n) {
judge();
} else {
for (int k = 1; k <= grade * grade; ++k) {
if (used[k] == false) {
square[n / grade][n % grade] = k;
used[k] = true;
dfs(n + 1);
used[k] = false;
}
}
}
}
// main函数
public static void main(String[] args) {
System.out.println("输入幻方的阶数:");
Scanner sc = new Scanner(System.in);
int grade = sc.nextInt();
sc.close();
MagicSquareDFS square = new MagicSquareDFS(grade);
square.dfs(0);
}
}