幻方问题:一个n*n的矩阵中填入1到n*n的数字,使得每一行每一列每条对角线的累加和都相等。

Posted tacit-lxs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了幻方问题:一个n*n的矩阵中填入1到n*n的数字,使得每一行每一列每条对角线的累加和都相等。相关的知识,希望对你有一定的参考价值。

题目:幻方又称魔方阵,游戏规则是在一一个n*n的矩阵中填入1到n*n的数字,使得每一行、每一列、每条对角线的累加和都相等。

思路:

回溯加剪枝:将矩阵用递归不重复的填满,用回溯的方法枚举每一种填入的情况,

比如arr[0][0]可以填入1到n*n的任意一个未被填入的数字。

然后判断是否满足幻方的条件。

代码:

public calss Main
        public static void main(String[] args) 
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入行数:");
            int N = scanner.nextInt();
            System.out.println("请输入列数:");
            int M = scanner.nextInt();
            int num = N*M+1;
            myPrintAnswer(N,M,num);
        
	private static void myPrintAnswer(int n, int m, int num) 
        int[][] arr = new int[n][m];
        int total = 0;
        for (int i = 1; i < num; i++) 
            total  += i;
        
        //根据total可以算出幻方的各行、各列及对角线之和的值:total/行数或列数
        System.out.println(total);
        boolean[] booleans = new boolean[num];
        dfs(0,arr,booleans,num,n,m,total);
    
	//递归的将arr填满
    private static void dfs(int i,int[][] arr, boolean[] booleans,int num,int n,int m,int total) 
        if (i == num - 1 && check(arr))
//打印结果
            myPrint(arr);
            System.out.println("-------");
            return;
        
        if(i >= n )
            int sum = 0;
            for (int j = 0; j < arr[0].length; j++) 
                sum += arr[0][j];
            
//剪枝
            if(sum != total/n) return;
        
        for (int k = 1; k < num; k++) 
            if(!booleans[k])
                booleans[k] = true;
                arr[i/m][i%m] = k;
                dfs(i+1,arr,booleans,num,n,m,total);
                booleans[k] = false;
            

        
    
    //打印矩阵
    private static void myPrint(int[][] arr) 
        for (int i = 0; i < arr.length; i++) 
            for (int j = 0; j < arr[0].length; j++) 
                if(j <arr.length -1)
                    System.out.print( arr[i][j]+ "-");
                else
                    System.out.print(arr[i][j]);
                
            
            System.out.println();
        
    
    //判断是否满足构成幻方条件
    private static boolean check(int[][] arr) 
        int num = 0;
        for (int i = 0; i < arr[0].length; i++) 
            num += arr[0][i];
        
        //求每行之和
        for(int i = 0;i < arr[0].length;i++)
            int num1 = 0;
            for (int j = 0; j < arr.length; j++) 
                num1 += arr[i][j];
            
            if(num != num1) return false;
        
        //求每列之和
        for (int i = 0; i < arr.length; i++) 
            int num2 = 0;
            for (int j = 0; j < arr[0].length; j++) 
                num2 += arr[j][i];
            
            if(num != num2) return false;
        
        int i = 0,j = 0;
        int num3 = 0;
        //对角线之和
        while (i < arr.length && j < arr.length)
            num3 += arr[i][j];
            i++;
            j++;
        
        if(num3 != num) return false;
        i = 0;
        j = arr[0].length-1;
        int num4 = 0;
        while (i < arr.length && j >= 0)
            num4 += arr[i][j];
            i++;
            j--;
        
        if(num4 != num) return false;
        return true;
    

以上是关于幻方问题:一个n*n的矩阵中填入1到n*n的数字,使得每一行每一列每条对角线的累加和都相等。的主要内容,如果未能解决你的问题,请参考以下文章

C++中,怎么输出一个n阶矩阵呢?

算法33---矩阵中的幻方

[解题报告][搜索+剪枝技巧]幻方

P1978 神奇的幻方

神奇的幻方(模拟)

-神奇的幻方