您的位置:首页 > 编程语言 > Java开发

2015蓝桥杯决赛Java A组 第二题--四阶幻方

2016-06-29 00:56 573 查看
//把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

虽然经过剪枝,但是这个算法还是非常耗时的,大概一两分钟才能得出结果,这种题应该是填空题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息