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
虽然经过剪枝,但是这个算法还是非常耗时的,大概一两分钟才能得出结果,这种题应该是填空题。
相关文章推荐