又一個數獨求解c++程式

lt發表於2016-09-29

很好懂,也挺快,原文用了1-9座標,還用了浮點運算,拖累了效率。改為0-8,速度提高了一倍。

/* this solving the sudo ku using hashing // bashed on the // advice list and the backtracking */

#include <stdio.h>
#include <math.h>
// #include
int sudoku[9][9] = {
    {0, 8, 0, 0, 0, 9, 0, 7, 2},
    {6, 0, 0, 0, 0, 0, 0, 0, 4},
    {0, 5, 0, 0, 6, 0, 9, 0, 1},
    {2, 0, 0, 0, 0, 5, 0, 0, 0},
    {3, 7, 6, 1, 8, 4, 2, 9, 5},
    {0, 0, 0, 3, 0, 0, 0, 0, 6},
    {9, 0, 1, 0, 2, 0, 0, 4, 0},
    {5, 0, 0, 0, 0, 0, 0, 0, 9},
    {8, 4, 0, 9, 0, 0, 0, 2, 0}}; // very hard

int row[9][10] = {0};    // this matrix used for the hashing the row and the digit
int col[9][10] = {0};    // this is for the hashing the column
int TCT[3][3][10] = {0}; // three cross three (for the three cross three matrix) to hashing the 3*3 board
int counter[10] = {0};
int l = 0;
struct advice // this take the information of about the list of the data that can be insereted into the matrix of // the sudo ku
{
    int i, j;
    int count;
    int adv[10];
};
long int total;

typedef struct advice advice;

advice adv1[81];

void advicearray(advice *adv);

/* this method for the setting the those position that is filled already in the matrix (row , col , TCT->three cross )
 // in the TCT we are using the hasing */

void initial()
{
    int i, j; //, m,n;
    for (i = 0; i < 9; i++)
    {
        for (j = 0; j < 9; j++)
        {
            if (sudoku[i][j])
            {
                row[i][sudoku[i][j]] = 1;
                col[j][sudoku[i][j]] = 1;
                TCT[i / 3][j / 3][sudoku[i][j]] = 1;
            }
        }
    }
}

// based on the initialization we can create the list of the of unfilled with and the possible input that is advice list
void advicearray(advice *adv1)
{
    int i, j, k, counter[10] = {0}, m;
    l = 0;
    for (i = 0; i < 9; i++)
    {
        for (j = 0; j < 9; j++)
        {
            if (!sudoku[i][j])
            {
                for (k = 1; k < 10; k++)
                    counter[k] = row[i][k] || col[j][k] || TCT[i / 3][j / 3][k];

                m = 1;
                for (k = 1; k < 10; k++)
                {
                    if (!counter[k])
                        adv1[l].adv[m++] = k;
                    counter[k] = 0;
                }
                adv1[l].count = m;
                adv1[l].i = i;
                adv1[l].j = j;
                l++;
            }
        }
    }
}
void print()
{
    int i, j;
    for (i = 0; i < 9; i++)
    {
        for (j = 0; j < 9; j++)
            printf("%d ", sudoku[i][j]);
        putchar('\n');
    }
}

/* this is the main logic for the solving the sudo ku using hasing and the back-tracking */

int sudoku_solver(int i, int j, int lb, int ub)
{
    int k, p, m, num; // next num

    if (lb == ub)
        return 1;

    for (k = 1; k < adv1[lb].count; k++)
    {
        total++;
        num = adv1[lb].adv[k];
        p = row[i][num] || col[j][num] || TCT[i / 3][j / 3][num]; /// checking the row col and TCT
        if (p == 0)                                               // recursive call
        {
            sudoku[i][j] = num;
            row[i][num] = 1;
            col[j][num] = 1;
            TCT[i / 3][j / 3][num] = 1;
            if (!sudoku_solver(adv1[lb + 1].i, adv1[lb + 1].j, lb + 1, ub))
            {
                row[i][num] = 0;
                col[j][num] = 0;
                TCT[i / 3][j / 3][num] = 0;
                sudoku[i][j] = 0;
            }
            else
                return 1;
        }
    }
    return 0;
}

int main()
{
    char s[] = "000000010400000000020000000000050407008000300001090000300400200050100000000806000";
    for (int i = 0; i < 9; i++)
        for (int j = 0; j < 9; j++)
            sudoku[i][j] = s[i * 9 + j] - '0';
    initial();
    advicearray(adv1);
    if (sudoku_solver(adv1[0].i, adv1[0].j, 0, l))
        ;
    print();
    return 0;
}

相關文章