Sudoku 数独 (Dancing links)

来源:互联网 发布:中国电信云计算干嘛的 编辑:程序博客网 时间:2024/05/16 02:30

Sudoku

Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u
SubmitStatus

Description

In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.

Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.

Input

The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.

Output

For each test case, print a line representing the completed Sudoku puzzle.

Sample Input

.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.end

Sample Output

527389416819426735436751829375692184194538267268174593643217958951843672782965341416837529982465371735129468571298643293746185864351297647913852359682714128574936


题意:数独 略


思路:

主要问题就是转化成精确覆盖问题 然后用Dancing links 求解就行了 

关键是如何转换 行为决策 列为要求解的问题

列:

r 列 c 列要有值 81列

r 列要有1-9,9*9=81列

c 列要有1-9,9*9=81列

r行c列所处的九宫格要有1-9,9*9=81列

所以共9*9*4列

行:

每行表示一个决策

一行(决策)表示为一个(r, c, v)三元组 表示r行c列填v 所以最多一共有9*9*9行

一行可以完成的是:

1. r行c列有值

2. r行有v

3. c列有v

4.r行c列所处的九宫格有v

所以问题就是 这个01矩阵的精确覆盖问题


#include <cstdio>#include <iostream>#include <vector>#include <algorithm>#include <cstring>#include <string>#include <map>#include <cmath>#include <queue>#include <set>using namespace std;//#define WIN#ifdef WINtypedef __int64 LL;#define iform "%I64d"#define oform "%I64d\n"#elsetypedef long long LL;#define iform "%lld"#define oform "%lld\n"#endif#define S64I(a) scanf(iform, &(a))#define P64I(a) printf(oform, (a))#define REP(i, n) for(int (i)=0; (i)<n; (i)++)#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)const int INF = 0x3f3f3f3f;const double eps = 10e-9;const double PI = (4.0*atan(1.0));const int maxn = 30000 + 20;int U[maxn], D[maxn], L[maxn], R[maxn], S[maxn];int H[maxn];int COL[maxn], ROW[maxn];int size;int rows;int dataRow[maxn];int dataCol[maxn];int dataV[maxn];int ans[9][9];int opr[maxn][3];void init(int cols) {    for(int i=0; i<=cols; i++) {        U[i] = D[i] = i;        L[i] = i-1;        R[i] = i+1;        S[i] = 0;    }    R[cols] = 0;    L[0] = cols;    size = cols+1;    memset(H, -1, sizeof(H));}void insert(int row, int col) {    U[size] = U[col];    D[size] = col;    D[U[col]] = size;    U[col] = size;    if(H[row] == -1) {        H[row] = R[size] = L[size] = size;    } else {        int rh = H[row];        R[size] = rh;        L[size] = L[rh];        R[L[rh]] = size;        L[rh] = size;    }    S[col]++;    COL[size] = col;    ROW[size] = row;    size++;}void remove(int c) {    L[R[c]] = L[c];    R[L[c]] = R[c];    for(int i=D[c]; i!=c; i=D[i]) {        for(int j=R[i]; j!=i; j=R[j]) {            S[COL[j]]--;            U[D[j]] = U[j];            D[U[j]] = D[j];        }    }}void resume(int c) {    L[R[c]] = c;    R[L[c]] = c;    for(int i=D[c]; i!=c; i=D[i]) {        for(int j=L[i]; j!=i; j=L[j]) {            S[COL[j]]++;            U[D[j]] = j;            D[U[j]] = j;        }    }}bool dfs(int num) {    if(R[0] == 0) {        for(int i=0; i<num; i++) {            int r = opr[i][0];            int c = opr[i][1];            int v = opr[i][2];            ans[r][c] = v;        }        return true;    }    int c = R[0];    int mins = S[c];    for(int i=R[0]; i!=0; i=R[i]) if(S[i] < mins) {        c = i;        mins = S[i];    }    remove(c);    for(int i=D[c]; i!=c; i=D[i]) {        int r = ROW[i];        opr[num][0] = dataRow[r];        opr[num][1] = dataCol[r];        opr[num][2] = dataV[r];        for(int j=R[i]; j!=i; j=R[j]) remove(COL[j]);        if(dfs(num+1)) return true;        for(int j=L[i]; j!=i; j=L[j]) resume(COL[j]);    }    resume(c);    return false;}void addGrid(int r, int c, int v) {    insert(rows, (r-1) * 9 + c);    int baseRowV = 81;    insert(rows, baseRowV + (r-1) * 9 + v);    int baseColV = baseRowV + 81;    insert(rows, baseColV + (c-1) * 9 + v);    int baseGridV = baseColV + 81;    int grid = (r-1) / 3 * 3+ (c-1) / 3;    insert(rows, baseGridV + grid * 9 + v);    dataRow[rows] = r;    dataCol[rows] = c;    dataV[rows] = v;    rows++;}char puzzle[100];int main() {    while(scanf("%s", puzzle) != EOF && strcmp(puzzle, "end")) {        int cols = 9*9*4;        rows = 1;        init(cols);        for(int i=0; i<81; i++) {            int r = i / 9 + 1;            int c = i % 9 + 1;            int grid = i / 9 + 1;            if(puzzle[i] == '.') {                for(int k=1; k<=9; k++) {                    addGrid(r, c, k);                }            } else {                addGrid(r, c, puzzle[i] - '0');            }        }        dfs(0);        REP1(i, 9) REP1(j, 9) putchar(ans[i][j] + '0');        putchar('\n');    }    return 0;}





0 0
原创粉丝点击