Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 7877 | Accepted: 2792 |
Description
In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,
. | 2 | 7 | 3 | 8 | . | . | 1 | . |
. | 1 | . | . | . | 6 | 7 | 3 | 5 |
. | . | . | . | . | . | . | 2 | 9 |
3 | . | 5 | 6 | 9 | 2 | . | 8 | . |
. | . | . | . | . | . | . | . | . |
. | 6 | . | 1 | 7 | 4 | 5 | . | 3 |
6 | 4 | . | . | . | . | . | . | . |
9 | 5 | 1 | 8 | . | . | . | 7 | . |
. | 8 | . | . | 6 | 5 | 3 | 4 | . |
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
527389416819426735436751829375692184194538267268174593643217958951843672782965341 416837529982465371735129468571298643293746185864351297647913852359682714128574936
Source
题意:给出一个数独的起始状态,要你找出一个符合要求的填法。
思路:这个题目能够转换为精确覆盖的模型。列中有(r,v) 行r中必须要有数字v,(c,v)列c中必须要有数字v,(r,c)行r列c的格子中必须要有数字,(slot,v)slot分块必须要有数字v。 行的话是(r,c,v)表示在(r,c) 处填入数字v。 由于选取一些行后列中的必须有且仅有一个1才能满足。所以这个是一个精确覆盖问题。到这里自己建好矩阵的0、1就行了。
代码:
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int maxn = 4 * 9 * 9;
const int N = 9 * 9 * 9 * 4 * 9 * 9 + 100;
//column: (r,v) 9*9 , (c,v) 9*9 , (slot,v) 9*9 , (r,c) 9*9 ; 4*9*9
#define FOR(i , s , A) for(int i=A[s];i!=s;i=A[i])
int code(int a, int b, int c)
{
return a * 81 + b * 9 + c;
}
void decode(int x, int&a, int&b, int&c)
{
c = x % 9;
x /= 9;
b = x % 9;
a = x / 9;
}
inline int getx(int i, int j, int v) { return i * 81 + j * 9 + v; }
inline void GetWay(int x, int&i, int&j, int&v)
{
v = x % 9; x /= 9;
j = x % 9; x /= 9;
i = x;
}
int U[N], D[N], L[N], R[N];
int S[N],cnt;
int col[N], row[N];
int M[maxn*2];
inline void LRremove(int x) { L[R[x]] = L[x]; R[L[x]] = R[x]; }
inline void LRresume(int x) { L[R[x]] = R[L[x]] = x; }
inline void UDremove(int x) { U[D[x]] = U[x]; D[U[x]] = D[x]; }
inline void Upresume(int x) { U[D[x]] = D[U[x]] = x; }
void RemoveColumn(int c)
{
LRremove(c);
FOR(i, c, D) {
FOR(j, i, R) {
--S[col[j]];
UDremove(j);
}
}
}
void ResumeColumn(int c)
{
FOR(i, c, U) {
FOR(j, i, L) {
++S[col[j]];
Upresume(j);
}
}
LRresume(c);
}
void add_row(int r)
{
int q = cnt;
for (int i = 1; i <= maxn; ++i) if (M[i])
{
U[cnt] = U[i]; D[cnt] = i;
L[cnt] = cnt - 1; R[cnt] = cnt + 1;
D[U[cnt]] = cnt; U[i] = cnt;
col[cnt] = i; row[cnt] = r;
++S[i];
++cnt;
}
L[q] = cnt - 1, R[cnt - 1] = q;
}
char maze[9*9+5];
int out[15][15];
bool read()
{
scanf("%s", maze);
if (maze[0] == 'e') return false;
cnt = 0;
for (int i = 0; i <= maxn; ++i)
{
col[i] = i;
L[i] = i - 1, R[i] = i + 1;
U[i] = D[i] = i;
++cnt;
}
L[0] = cnt - 1; R[cnt - 1] = 0;
D[0] = U[0] = 0;
memset(S, 0, sizeof(S));
for (int i = 0; i < 9;++i)
for (int j = 0; j < 9;++j)
for (int v = 0; v < 9; ++v) {
memset(M, 0, sizeof(M));
int x = code(0, i, v)+1; M[x] = 1;
x = code(1, j, v)+1; M[x] = 1;
x = code(2, i, j)+1; M[x] = 1;
x = code(3, i / 3 * 3 + j / 3, v)+1; M[x] = 1;
add_row(getx(i, j, v));
}
//r:0 c:1 (r,c):2 slot:3
int now = 0;
for (int i = 0; i < 9;++i)
for (int j = 0; j < 9; ++j) if (maze[now++] != '.')
{
int v = maze[now-1]-'1';
out[i][j] = v + 1;
int x = code(0, i, v)+1; RemoveColumn(col[x]);
x = code(1, j, v)+1; RemoveColumn(col[x]);
x = code(2, i, j)+1; RemoveColumn(col[x]);
x = code(3, i / 3 * 3 + j / 3, v)+1; RemoveColumn(col[x]);
}
return true;
}
int ans[9 * 9+10],top;
bool dfs()
{
if (R[0] == 0)
return true;
int c = R[0];
FOR(i, 0, R)
if (S[c] > S[i]) c = i;
if (R[0] == 0) return false;
RemoveColumn(c);
FOR(i, c, D) {
FOR(j, i, R) RemoveColumn(col[j]);
ans[top++] = row[i];
if (dfs()) return true;
--top;
FOR(j, i, L) ResumeColumn(col[j]);
}
ResumeColumn(c);
return false;
}
void solve()
{
top = 0;
dfs();
for (int i = 0; i < top; ++i) {
int r, c, v;
GetWay(ans[i], r, c, v);
out[r][c] = v+1;
}
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j)
printf("%d", out[i][j]);
// puts("");
}
puts("");
}
int main()
{
while (read()) {
solve();
}
}