用回溯解决数独 - C ++

时间:2016-11-20 08:32:58

标签: c++ backtracking sudoku

所以我试图用回溯来解决数独

这个例子: example_pic

我使用webSudoku(上图)给出的位置上的数字对二维数组中的一些索引进行了硬编码。 它肯定有解决方案,但我的代码打印“解决方案不存在

这是我的代码:

#include <stdio.h>
int a[10][10]= {{2,0,0,0,9,0,0,3,1},
            {0,0,3,5,0,6,0,2,0},
            {0,0,8,1,3,0,5,4,0},
            {7,2,0,0,0,9,0,0,4},
            {4,0,0,0,0,0,0,0,8},
            {3,0,0,6,0,0,0,9,5},
            {0,7,6,0,4,5,1,0,0},
            {0,1,0,9,0,7,4,0,0},
            {5,3,0,0,8,0,0,0,6}};

bool is_valid(int x, int y, int value){
    if(a[x][y] != 0) return false;

    //check_row and column
    for(int tmp=1; tmp<=9; tmp++){
        if(value == a[x][tmp]) return false;
    }
    for(int tmp=1; tmp<=9; tmp++){
        if(value == a[tmp][y]) return false;
    }
    //check in 3*3 block
    int x_s = (x-1)/3*3 + 1;
    int y_s = 3*((y+2)/3-1)+1;
    for(int ch_x = x_s; ch_x<x_s+3; ch_x++){
        for(int ch_y=y_s; ch_y<y_s+3; ch_y++){
            if(ch_x!=x && ch_y!=y){
                if(value==a[ch_x][ch_y]) return false;
            }
        }
    }
    return true;
}

bool find(int &x, int &y){
    // check if valid cells are exists
    for(x=1; x<=9; x++){
        for(y=1; y<=9; y++){
            if(a[x][y] == 0)
                return true;
        }
    } 
    return false;
}

bool solve(){
    int x,y;
    //base::case
    if(!find(x,y)) return true;
    for(int cand = 1; cand <=9; cand++){
        if(is_valid(x,y,cand)){
            a[x][y] = cand;
            if(solve()) return true;
            a[x][y] = 0;
        }
    }
    return false;
}

void print(){
    //print the sudoku plate
    for(int i=1;i<=9; i++){
        for(int j=1; j<=9; j++){
            printf("%2d",a[i][j]);
        }
        printf("\n");
    }
    return ;
}

int main(){
    //Fill in some empty grid with the known values
    /*for(int i=1; i<=9; i++){
        for(int j=1; j<=9; j++){
        scanf("%1d",&a[i][j]);
        }
    }*/

    if (solve()) print();
    else printf("No solution exists\n");
    return 0;
}

我猜我的'解决功能'或'is_valid'功能无效。

在'is_valid'函数中,如果有问题,则为

bool find(int &x, int &y){
// check if valid cells are exists
    for(x=1; x<=9; x++){
        for(y=1; y<=9; y++){
            if(a[x][y] == 0)
                return true;
        }
    }
    return false;
} 

但是,我也对这部分进行了硬编码,在我的范围内,似乎没有问题。

在'解决功能'中

bool solve(){
    int x,y;
    //base::case
    if(!find(x,y)) return true;
    for(int cand = 1; cand <=9; cand++){
        if(is_valid(x,y,cand)){
            a[x][y] = cand;
            if(solve()) return true;
            a[x][y] = 0;
        }
    }
    return false;
}

我无法弄清楚我错在哪里。如果你在solve()函数中发现任何其他错误 - 请告诉我。因为我不确定我完全理解“回溯”的事情......

P.S。 :参考我读过(https://see.stanford.edu/materials/icspacs106b/H19-RecBacktrackExamples.pdf

1 个答案:

答案 0 :(得分:1)

有一些错误

  • 您正在混淆(x, y)(row, col)地址(行是y,而不是x)。选择一个表示并坚持下去
  • is_valid中存在拼写错误,因为对(c, x)的检查应该在(c, y)(或(y, c)上,具体取决于约定,但肯定会使用y而不是再次x
  • 3x3子块计算错误...正确的公式可以是例如int start_x = (x-1)/3*3 + 1, start_y = (y-1)/3*3 + 1;

修复代码在给定示例上工作的所有内容