【问题标题】:Need help for optimization - generating magic squares in java需要优化帮助——在java中生成魔方
【发布时间】:2014-06-01 04:54:41
【问题描述】:

我必须实现一种算法,该算法为给定的边长 (n=3,4) 创建所有可能的幻方。对于 n=3,算法运行良好。但是对于 n=4,算法没有得到任何结果,因为它不是最优的(太慢了)。我试图优化算法,但它仍然无法正常工作。 非常感谢任何帮助。

public class MagicSquare {

private int[][] square;
private boolean[] possible;
private int totalSqs;
private int sum;
private static int numsquares;


public MagicSquare(int n){
    square = new int[n][n];
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            square[i][j] = 0;
        }
    }

    totalSqs = n*n;
    possible = new boolean[totalSqs];
    for(int i=0; i<totalSqs; i++)
        possible[i] = true;

    sum = n*(n*n+1)/2;
    numsquares = 0;
    fill(0, 0);
}

public void fill(int row, int col){
    for(int i=0; i<totalSqs; i++){
        if(possible[i]){
            square[row][col] = i+1;
            possible[i] = false;

            int newcol = col+1;
            int newrow = row;
            if(newcol == square.length){
                newrow++;
                newcol = 0;
            }

            fill(newrow,newcol);
            square[row][col] = 0;
            possible[i] = true;
        }
    }

    if(!checkRows() || !checkCols())
        return;

    if(row == square.length){
        for(int i=0; i<square.length; i++ ){
            for(int j=0; j<square[i].length; j++){
                System.out.print(square[i][j]+" ");
            }
            System.out.println();
        }
        System.out.println();
        numsquares++;
        return;
    }
}

public boolean checkRows(){
    for(int i=0; i<square.length; i++){
        int test = 0;
        boolean unFilled = false;

        for(int j=0; j<square[i].length; j++){
            test += square[i][j];
            if(square[i][j] == 0)
                unFilled = true;
        }

        if(!unFilled && test!=sum)
            return false;
    }
    return true;
}

public boolean checkCols(){
    for(int j=0; j<square.length; j++){
        int test = 0;
        boolean unFilled = false;

        for(int i=0; i<square[j].length; i++){
            test += square[i][j];
            if(square[i][j] == 0)
                unFilled = true;
        }

        if(!unFilled && test!=sum)
            return false;
    }
    return true;
}

public static void main(String[] args) {
    new MagicSquare(3);
    System.out.println(numsquares);
}

}

【问题讨论】:

标签: java memory optimization recursion magic-square


【解决方案1】:

您可以引入其他数组来跟踪行、列和 2 条对角线上的总和。每当您在方格中放置一个新数字或从中删除一个数字时,您都需要更新这些总和。注意当你有一个奇数维度的情况下,中间的数字属于两条对角线,所以两条对角线的和都需要更新。

您有 4 个案例:

  1. 您有一个行几乎已满(例如,维度是 3,并且您在第一行中已经有 2 个数字。那么您不必猜测第三个数字,您可以通过从魔术总和中减去第一行的总和来得到它,并且给定,它仅取决于维度)
  2. (特定情况)最后一行几乎满了最后一列几乎满了第一个对角线几乎满了(第一column 作为从左上角元素开始并以右下角元素结束的列)。这基本上是幻方中的最后一个位置。
  3. 您的列几乎已满
  4. (特定情况)您的第一列几乎已满,因此您也有第二列几乎已满(第二列是从顶部开始的列右元素并以左下元素结束)
  5. (+1)普通情况

在每种情况下,您都可以减少回溯,因为您不必猜测丢失的数字。这可以减少所需的时间。

此外,如果您在对角线上插入元素,然后再在其他位置插入元素,这将为您赢得额外的时间,因为大多数错误都发生在对角线上。如果你想要它真的非常快,可以考虑用 C/C++ 编写代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-27
    相关资源
    最近更新 更多