【问题标题】:C programming - Sodoku solution (backtracking)C编程——数独解决方案(回溯)
【发布时间】:2021-04-15 04:50:21
【问题描述】:

问题是:从用户的数独板中获取,如果有解决方案打印它,如果没有打印没有解决方案! soduko的解决方法:两个相同的数字不能出现在同一行; 两个相同的数字不能出现在同一列中。 我编写了一个程序,当我放置 soduko 板和大小(全局参数 - 如我的代码所示)时,我编写了一个完美运行的程序,但是当我尝试从用户那里接收时,运行解决方案花费了很多时间,有时它没有重新调整任何东西。我想知道为什么?!

#include <stdio.h>
#include <stdlib.h>

#define SIZE 5


int matrix[5][5] = {
    {4,2,0,0,5},
    {2,0,0,1,3},
    {5,0,1,2,0},
    {0,0,3,0,2},
    {0,0,0,0,0},
};


void print_sudoku()
{
    int i,j;
    for(i=0;i<SIZE;i++)
    {
        for(j=0;j<SIZE;j++)
        {
            printf("%d ",matrix[i][j]);
        }
        printf("\n");
    }
}


int number_unassigned(int *row, int *col)
{
    int num_unassign = 0;
    int i,j;
    for(i=0;i<SIZE;i++)
    {
        for(j=0;j<SIZE;j++)
        {
            if(matrix[i][j] == 0)
            {
                *row = i;
                *col = j;
                num_unassign = 1;
                return num_unassign;
            }
        }
    }
    return num_unassign;
}


int is_safe(int n, int r, int c)
{
    int i;

    for(i=0;i<SIZE;i++)
    {
        if(matrix[r][i] == n)
            return 0;
    }
    for(i=0;i<SIZE;i++)
    {
        if(matrix[i][c] == n)
            return 0;
    }
    return 1;
}


int solve_sudoku()
{
    int row;
    int col;
 
    if(number_unassigned(&row, &col) == 0)
        return 1;

    int i;

    for(i=1;i<=SIZE;i++)
    {
  
        if(is_safe(i, row, col))
        {
            matrix[row][col] = i;

            if(solve_sudoku())
                return 1;

            matrix[row][col]=0;
        }
    }
    return 0;
}


int main()
{
    if (solve_sudoku())
        print_sudoku();
    else
        printf("No solution!\n");
    return 0;
}

这是我用来要求用户进入数独板的代码:

int** ReadSoduko(int n) {
    int** matrix = (int**) malloc((sizeof(int*)) * n);
    for(int i = 0; i < n; ++i) {
        matrix[i] = malloc(sizeof(int) * n);
    }
    printf("\nEnter your soduko board:\n");
    for(int i = 0; i < n; ++i) {
          printf("Enter row [%d]: ", i);
        for(int j = 0; j < n; ++j) {
            scanf("%d", &matrix[i][j]);
        }
    }
    return matrix;
}

【问题讨论】:

  • 棋盘有 1 到 9 的数字,但求解器只检查 1 到 5 的数字:for(i=1;i&lt;=SIZE;i++)。使用 1 到 5 可能没有解决方案,因此求解器需要检查所有可能性。如果有 12 个空格,则需要 5^12 = 244e6 次尝试才能确定没有解决方案。如果用户用更多空白空间制作更大的板,则可能需要更长的时间。
  • 对不起,我更正了矩阵,在这个问题中,他们要求假设输入是正确的。该代码对我有用。我的问题是,当我试图让用户插入他的数独板时,我在运行它时遇到了问题。
  • 该程序运行得非常好(执行时间 0.047 秒),正如我所说的,程序本身没有问题,但是当我用函数 ReadSodoku 替换矩阵时,运行它时遇到问题。
  • 好的,然后显示该代码。

标签: c recursion backtracking


【解决方案1】:

我怀疑您的问题与一件事有关:#define SIZE 您可能在动态阅读时忘记更新。由于您在循环中使用SIZE,如果这不是矩阵的实际大小,那么它可能无法正常工作。我更改了 2 行并添加了其他 3 行(末尾带有 cmets 的行)。立即尝试。

#include <stdio.h>
#include <stdlib.h>

int SIZE; //changed here

int** matrix; //changed here

void print_sudoku()
{
    int i, j;
    for (i = 0; i < SIZE; i++)
    {
        for (j = 0; j < SIZE; j++)
        {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}


int number_unassigned(int* row, int* col)
{
    int num_unassign = 0;
    int i, j;
    for (i = 0; i < SIZE; i++)
    {
        for (j = 0; j < SIZE; j++)
        {
            if (matrix[i][j] == 0)
            {
                *row = i;
                *col = j;
                num_unassign = 1;
                return num_unassign;
            }
        }
    }
    return num_unassign;
}


int is_safe(int n, int r, int c)
{
    int i;

    for (i = 0; i < SIZE; i++)
    {
        if (matrix[r][i] == n)
            return 0;
    }
    for (i = 0; i < SIZE; i++)
    {
        if (matrix[i][c] == n)
            return 0;
    }
    return 1;
}


int solve_sudoku()
{
    int row;
    int col;

    if (number_unassigned(&row, &col) == 0)
        return 1;

    int i;

    for (i = 1; i <= SIZE; i++)
    {

        if (is_safe(i, row, col))
        {
            matrix[row][col] = i;

            if (solve_sudoku())
                return 1;

            matrix[row][col] = 0;
        }
    }
    return 0;
}


int** ReadSoduko(int n) {
    int** matrix = (int**)malloc((sizeof(int*)) * n);
    for (int i = 0; i < n; ++i) {
        matrix[i] = (int*) malloc(sizeof(int) * n);
    }
    printf("\nEnter your soduko board:\n");
    for (int i = 0; i < n; ++i) {
        printf("Enter row [%d]: ", i);
        for (int j = 0; j < n; ++j) {
            scanf("%d", &matrix[i][j]);
        }
    }
    return matrix;
}

int main()
{
    printf("Size of matrix: "); //added this
    scanf("%d", &SIZE); //added this
    matrix = ReadSoduko(SIZE); //added this
    if (solve_sudoku())
        print_sudoku();
    else
        printf("No solution!\n");
    return 0;
}

别忘了你静态声明的矩阵没有解!我已经测试了相同的矩阵,只是replacing the 2 in first line by a 0,它在这里工作。

【讨论】:

  • 谢谢,现在成功了。但是现在执行时间很长,他们要求我们想出一个可以在几秒钟内完成的代码。我需要想办法改进它
  • 是否必须动态分配?由于缓存未命中,您可能正在失去速度。也许您可以静态分配一个更大的矩阵并仅使用您需要的数量。或者你可以分配一个大小为 N * N 的数组。
  • 该代码适用于我提供的每个数独板,但对于 9*9 的数独没有解决方案它不起作用..你知道为什么吗?
  • 不起作用是什么意思?它希望它做什么而不是它在做什么?有哪些价值观?
猜你喜欢
  • 1970-01-01
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 2012-03-30
  • 1970-01-01
  • 2021-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多