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

//把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

 

虽然经过剪枝,但是这个算法还是非常耗时的,大概一两分钟才能得出结果,这种题应该是填空题。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值