魔方回溯和递归C ++

时间:2016-10-23 20:31:47

标签: c++ recursion backtracking

我正在尝试使用C ++中的Backtracking和recursion来解决C ++中的magic square问题。特别适用于4x4阵列。

4x4魔方解决方案的示例如下,其中每行,每列和对角线添加34:

enter image description here

我所做的更改是:用户输入一些将启动算法的值。

我的算法是:

enter image description here

here您可以更好地欣赏图片

我有一个关于算法如何解决带有回溯和递归的魔术方问题的概念,但我遇到了问题。

其中一个是:

成就不会使我的算法“忽略”用户已输入的值。

我在C ++中的代码位于Github的 link 中。这是代码:

#include <iostream>

using namespace std;

int sudoku[4][4];

int row = 0;
int column = 0;

bool isFull(int s[4][4]){
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < 4; j++){
            if(s[4][4] == 0){
                return false;
            }
        }
    }

    return true;
}

void printMatrix(int s[4][4]){
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < 4; j++){
            cout << sudoku[i][j] << "  ";
        }
        cout << endl;
    }
}

bool isAssigned(int row, int column){
    if(row == 1 && column == 0 ||
       row == 0 && column == 2 ||
       row == 1 && column == 2){
        return true;
    } else return false;
}

bool verify(int s[4][4], int row, int column){

    bool flag = false;

    int sumrow = 0, sumcolumn = 0, sumDiagonal = 0, sumDiagonal2 = 0;
    int value = 3;
    for(int i = 0; i < 4; i++){
        sumrow = sumrow + s[row][i];
        sumcolumn = sumcolumn + s[i][column];
        sumDiagonal = sumDiagonal + s[i][i];
        sumDiagonal2 = sumDiagonal2 + s[i][value];
        value--;
    }

    if(sumrow <= 34 && sumcolumn <= 34 && sumDiagonal2 <= 34 && sumDiagonal2 <= 34){
        return true;
    } else return false;

}

bool backtracking(int s[4][4], int row, int column){

    if(isFull(s) == true){ //verify if there are no zeros in the matrix
        printMatrix(sudoku);
        cout<<"Solution find ";
    }
    else {

        if(isAssigned(row, column) == false){ // verify if the cell is already assigned

            for(int i = 1; i <= 16; i++){

                s[row][column] = i; // assigned value

                if(verify(s, row, column) == true){ // verify that the sum of the column, row and diagonal not greater 34

                    if(column == 4) {
                            row++;
                            column=0;
                    }

                    backtracking(s, row, column + 1); // recursion
                    printMatrix(s); // Print the matrix to see progress
                    cout<<endl;

                } else { // the sum value exceeds 34
                    s[row][column] = 0;
                    return false;
                }
            }
        }
    }
}

int main(){

    sudoku[1][0] = 5;
    sudoku[0][2] = 15;
    sudoku[1][2] = 10;

    backtracking(sudoku, row, column);

    return 0;
}

我的algorithm主要是以下内容:

enter image description here

在这种情况下显然有一些功能,但是如果你看到我的code,你就会意识到我会尝试做什么。

也许我的解决方法不起作用或不好。

本出版物的原因是,我需要帮助改进或需要帮助来解决代码问题。这是我运行的主要功能和输出:

bool backtracking(int s[4][4], int row, int column){

    if(isFull(s) == true){ //verify if there are no zeros in the matrix
        printMatrix(sudoku);
        cout<<"Solution find ";
    }
    else {

        if(isAssigned(row, column) == false){ // verify if the cell is already assigned

            for(int i = 1; i <= 16; i++){

                s[row][column] = i; // assigned value

                if(verify(s, row, column) == true){ // verify that the sum of the column, row and diagonal not greater 34

                    if(column == 4) {
                            row++;
                            column=0;
                    }

                    backtracking(s, row, column + 1); // recursion
                    printMatrix(s); // Print the matrix to see progress
                    cout<<endl;

                } else { // the sum value exceeds 34
                    s[row][column] = 0;
                    return false;
                }
            }
        }
    }
}

输出:

3  16  15  0
5  0  10   0
0  0  0    0
0  0  0    0

正如我之前所说,当我找到用户已分配的值时,我遇到了问题。 这是第一次使用回溯,这就是我觉得有点困难的原因。谢谢大家。

1 个答案:

答案 0 :(得分:0)

嗯,是的,

最近不得不做类似的事情,有些地方可以做到这一点&#34;修复&#34;

从位图(1-16)开始,为网格中已分配的数字。即。用户输入的那些已标记为&#34;已使用&#34;。 仅为尚未在该位图中标记的网格指定数字。如果你使用非递归方法,需要使用一个堆栈来知道已经测试过哪些&#34; unset&#34;回溯时。如果使用递归方法(只有16个深度递归;))将位图和已经放置的方块作为副本传递,而不是引用;)