C语言源代码如下,在Linux平台下用GCC编译通过并运行。附数据文件sudoku.dat及计算结果。
8--------
--36-----
-7--9-2--
-5---7---
----457--
---1---3-
--1----68
--85---1-
-9----4--
812753649
943682175
675491283
154237896
369845721
287169534
521974368
438526917
796318452
编译及运行方法:
gcc sudoku.c -o sudoku
./sudoku < sudoku.dat
#include <stdio.h>
#include <string.h>
#define ROWS 9
#define COLS 9
#define BLKS 9
#define NAN '-'
typedef enum { false = 0, true = !false } bool;
struct step {
char num[ROWS][COLS];
int cell[ROWS][COLS];
};
static int ctz(int x) { return __builtin_ctz(x); }
static int rowcol2blk(int row, int col) { return row / 3 * 3 + col / 3; }
static int blk2row(int blk) { return blk / 3 * 3; }
static int blk2col(int blk) { return blk % 3 * 3; }
bool setnum(struct step *curr, int row, int col, int num);
void init(struct step *curr)
{
int row, col;
for (row = 0; row < ROWS; ++row) {
for (col = 0; col < COLS; ++col) {
curr->cell[row][col] = 0x3FE;
curr->num[row][col] = NAN;
}
}
}
bool exclude(struct step *curr, int row, int col, int num)
{
int x = curr->cell[row][col] & ~(1 << num);
if (0 == x) return false;
curr->cell[row][col] = x;
if (NAN != curr->num[row][col] || 0 != (x & (x - 1)))
return true;
return setnum(curr, row, col, ctz(x));
}
bool setnum(struct step *curr, int row, int col, int num)
{
int mask = 1 << num;
int blk = rowcol2blk(row, col);
int r, c, r0, c0;
if (0 == (curr->cell[row][col] & mask))
return false;
curr->num[row][col] = '0' + num;
curr->cell[row][col] = mask;
for (r = 0; r < ROWS; ++r) {
if (r == row) continue;
if (!exclude(curr, r, col, num))
return false;
}
for (c = 0; c < COLS; ++col) {
if (c == col) continue;
if (!exclude(curr, row, c, num))
return false;
}
r0 = blk2row(blk);
c0 = blk2col(blk);
for (r = r0; r < r0 + 3; ++r) {
for (c= c0; c < c0 + 3; ++c) {
if (r == row && c == col) continue;
if (!exclude(curr, r, c, num))
return false;
}
}
return true;
}
bool try(struct step *curr)
{
struct step next;
int row, col, num;
int cell;
for (row = 0; row < ROWS; ++row) {
for (col = 0; col < COLS; ++col) {
if (NAN == curr->num[row][col])
goto outer;
}
}
outer:
if (row > ROWS) return true;
cell = curr->cell[row][col];
while (0 != cell) {
memcpy(&next, curr, sizeof next);
num = ctz(cell);
if (setnum(&next, row, col, num) && try(&next)) {
memcpy(curr, &next, sizeof *curr);
break;
}
cell &= ~(1 << num);
}
return (0 != cell);
}
int main()
{
struct step step;
int row, col, num;
init(&step);
for (row = 0; row < ROWS; ++row) {
for (col = 0; col < COLS; ++col) {
if (NAN == (num = getchar())) continue;
if (!setnum(&step, row, col, num - '0')) {
puts("no answer\n");
return 1;
}
}
num = getchar(); /* new line */
}
if (!try(&step)) {
puts("no answer\n");
return 1;
}
for (row = 0; row < ROWS; ++row) {
for (col = 0; col < COLS; ++col) {
putchar(step.num[row][col];
}
putchar('\n');
}
return 0;
}