//把1~16的数字填入4x4的方格中,使得行、列以及两个对角线的和都相等,满足这样的特征时称为:四阶幻方。
//
//四阶幻方可能有很多方案。如果固定左上角为1,请计算一共有多少种方案。
//比如:
// 1 2 15 16
// 12 14 3 5
// 13 7 10 4
// 8 11 6 9
//
//以及:
// 1 12 13 8
// 2 14 7 11
// 15 3 10 6
// 16 5 4 9
//
//就可以算为两种不同的方案
import java.util.LinkedList;
public class Main {
private static final int Element_NUM = 16;
private static final int ROW = 4;
private static final int COL = 4;
private static LinkedList<Integer> set = new LinkedList<Integer>();
private static int[][] arr = new int[ROW][COL];
private static int count = 0;
public static void main(String[] args) {
// TODO Auto-generated method stub
arr[0][0]=1;
set.add(1);
dfs(0, 1);
System.out.println(count);
}
/**
* 往数组放元素,回溯,剪枝
* @param row
* @param col
*/
private static void dfs(int row, int col) {
for (int i = 1; i <= Element_NUM; i++) {
if (!set.contains(i)) {
arr[row][col] = i;
set.add(i);
} else
continue;
//生成元素时判断前3行是否符合条件,不符合重新生成---
if (row == 0 && col == (COL-1 )) {
if (getRowSum(0) != 34) {
//print(true);
arr[row][col]=0;
set.removeLast();
if (i==Element_NUM) {
return;
}
continue;
}
}
if (row == 1 && col == (COL - 1)) {
if (getRowSum(1) != 34) {
arr[row][col]=0;
set.removeLast();
if (i==Element_NUM) {
return;
}
continue;
}
}
if (row == 2 && col == (COL - 1)) {
if (getRowSum(2) != 34) {
arr[row][col]=0;
set.removeLast();
if (i==Element_NUM) {
return;
}
continue;
}
}
//------------------------------
if (col < COL - 1)
dfs(row, col + 1);
else if (row < ROW - 1 && col == COL - 1)
dfs(row + 1, 0);
//到达最后一个数
if (row == ROW - 1 && col == COL - 1) {
//判断该矩阵是否符合四阶幻方
if(colIsReasonable()){
count++;
}
}
set.removeLast();
}
}
/**
* 获取某行的所有元素之和
* @param row
* @return
*/
private static int getRowSum(int row) {
int sum = 0;
for (int i = 0; i < COL; i++) {
sum += arr[row][i];
}
return sum;
}
/**
* 判断列和斜列是否合理
* @return
*/
private static boolean colIsReasonable() {
int sum=0;
//列,向下
for (int i = 0; i < COL; i++) {
for (int j = 0; j < ROW; j++) {
sum+=arr[j][i];
}
if(sum!=34)
return false;
sum=0;
}
sum=0;
//斜列,向右下
for (int i = 0; i < COL; i++) {
sum+=arr[i][i];
}
if(sum!=34)
return false;
sum=0;
//斜列,向右上
for (int i = COL-1; i >=0; i--) {
sum+=arr[i][COL-1-i];
}
if(sum!=34)
return false;
return true;
}
}
结果:416
虽然经过剪枝,但是这个算法还是非常耗时的,大概一两分钟才能得出结果,这种题应该是填空题。