Algorithm 回溯优化

Algorithm 回溯优化,algorithm,data-structures,backtracking,Algorithm,Data Structures,Backtracking,最近我试图解决著名的算法问题。在其中一个网站上,我读到我应该将棋盘分成黑白两部分来优化执行。之后,我应该使用回溯来计算将主教分别放在黑色方块和白色方块上的可能方法的数量 在下面的代码中,我尝试将6位主教放在8乘8棋盘的白色方块上。我这样做只是为了验证这项技术是否真的有效 //inside main function int k = 6; //number of bishops int n = 8; //length of one side of chessboard Integer[] posi

最近我试图解决著名的算法问题。在其中一个网站上,我读到我应该将棋盘分成黑白两部分来优化执行。之后,我应该使用回溯来计算将主教分别放在黑色方块和白色方块上的可能方法的数量

在下面的代码中,我尝试将6位主教放在8乘8棋盘的白色方块上。我这样做只是为了验证这项技术是否真的有效

//inside main function
int k = 6; //number of bishops
int n = 8; //length of one side of chessboard
Integer[] positions = new Integer[k];

long result = backtrack(positions, 0, n);

//find how many times we double counting each possible combination of bishops
int factor = 1;
for(int i = k; i>0; i--) {
    factor = factor * i;
}
System.out.println("The result is " + result/factor);


//implementation of other functions
public long backtrack(Integer[] prevPositions, int k, int n) {

    if(k == 6) {
        return 1;
    }
    long sum = 0;

    Integer[] candidates = new Integer[n*n];
    int length = getCandidates(prevPositions, k, candidates,  n);

    for(int i=0 ; i<length ; i++) {            
        prevPositions[k] = candidates[i];
        sum += backtrack(prevPositions,k+1,n);
    }

    return sum;
}

public Integer getCandidates(Integer[] prevPositions, int k, Integer[] candidates, int n) {
    int length = 0;
    //only white squares are considered as candidates, hence i+=2
    for (int i = 0; i < n*n; i+=2) {
        boolean isGood = true;
        int iRow = i / n;
        int iCol = i % n;

        for (int j = 0; j < k; j++) {
            int prev = prevPositions[j];
            if (i == prev) {
                isGood = false;
                break;
            } else {
                int prevRow = prev / n;
                int prevCol = prev % n;
                if (Math.abs(iRow - prevRow) == Math.abs(iCol - prevCol)) {
                    isGood = false;
                    break;
                }
            }
        }

        if(isGood) {
            candidates[length] = new Integer(i);
            length++;
        }
    }
    return length;
}

尽管我能理解为什么将棋盘分成黑白方块可以优化问题,但仍然需要大约11秒来计算将所有主教放在白色方块上的可能方法的数量。你能帮我吗?我做错了什么?

以下是一些改进搜索的方法

1代替生成和测试,可以考虑有限域搜索,其中每个主教都有可能的位置域。每当你任命一位主教时,你都会删减其余主教的领地。如果主教的域变为空,则必须回溯

2作为一种改进,如果要放置n个主教,并且m 3使用动态规划/记忆,存储1个bishop、2个bishop……的解,并从n个bishop解的集合中计算n+1个bishop解的集合

4利用对称性减少搜索空间。在这种情况下,至少存在黑/白对称和旋转/反射对称

5.努力寻找更好的代表。例如,位模式

6如果您使用不同的表示法,请研究使用trail cf.Prolog跟踪回溯时需要撤消的操作


干杯

以下是一些改进搜索的方法

1代替生成和测试,可以考虑有限域搜索,其中每个主教都有可能的位置域。每当你任命一位主教时,你都会删减其余主教的领地。如果主教的域变为空,则必须回溯

2作为一种改进,如果要放置n个主教,并且m 3使用动态规划/记忆,存储1个bishop、2个bishop……的解,并从n个bishop解的集合中计算n+1个bishop解的集合

4利用对称性减少搜索空间。在这种情况下,至少存在黑/白对称和旋转/反射对称

5.努力寻找更好的代表。例如,位模式

6如果您使用不同的表示法,请研究使用trail cf.Prolog跟踪回溯时需要撤消的操作


干杯

你看过这个吗?它能给你关于处理主教的想法吗?看看这个:它有一个n皇后的回溯应用程序,还有一个小主教的示例练习。你看过这个吗?它能给你关于处理主教的想法吗?你也可以看到:它有一个n皇后的回溯应用程序,还有一个小主教的示例练习。关于3,看起来你实际上可以在这里使用二进制除法。也就是说,2n个主教的解必须是两个独立的n个主教解的组合。这将是一个真正的省时!关于3,这里似乎可以使用二进制除法。也就是说,2n个主教的解必须是两个独立的n个主教解的组合。这将是一个真正的省时!