POJ 3074 Sudoku
Posted evenbao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3074 Sudoku相关的知识,希望对你有一定的参考价值。
【题目链接】
http://poj.org/problem?id=3074
【算法】
将数独问题转化为精确覆盖问题,用Dancing Links求解
转化方法如下 :
我们知道,在一个数独中 :
1.每个格子填且只填一个数
2.每一行填1-9这九个数
3.每一列填1-9这九个数
4.每个格子填1-9这九个数
对于第一个约束条件,我们用81列,表示是否填入
对于第二个约束条件,我们每一行用9列,表示这一行是否有1-9
第三,四个约束条件的处理方式和第二个类似
【代码】
#include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <exception> #include <fstream> #include <functional> #include <limits> #include <list> #include <map> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stdexcept> #include <streambuf> #include <string> #include <utility> #include <vector> #include <cwchar> #include <cwctype> #include <stack> #include <limits.h> using namespace std; #define MAXS 250000 int i,j,cnt; int mat[800][400]; char s[100]; struct info { int pos,val; } a[MAXS]; inline int getRow(int pos) { return (pos - 1) / 9 + 1; } inline int getCol(int pos) { return (pos - 1) % 9 + 1; } inline int getGrid(int pos) { int x = getRow(pos),y = getCol(pos); return (x - 1) / 3 * 3 + (y - 1) / 3 + 1; } struct DancingLinks { int n,m,step,size; int U[MAXS],D[MAXS],L[MAXS],R[MAXS],Row[MAXS],Col[MAXS]; int H[MAXS],S[MAXS]; int ans[MAXS]; inline void init(int _n,int _m) { int i; n = _n; m = _m; for (i = 0; i <= m; i++) { S[i] = 0; U[i] = D[i] = i; L[i] = i - 1; R[i] = i + 1; } L[0] = m; R[m] = 0; size = m; for (i = 1; i <= n; i++) H[i] = -1; } inline void link(int r,int c) { size++; Row[size] = r; Col[size] = c; S[c]++; D[size] = D[c]; U[D[c]] = size; U[size] = c; D[c] = size; if (H[r] < 0) L[size] = R[size] = H[r] = size; else { R[size] = R[H[r]]; L[R[H[r]]] = size; L[size] = H[r]; R[H[r]] = size; } } inline void Remove(int c) { int i,j; R[L[c]] = R[c]; L[R[c]] = L[c]; for (i = D[c]; i != c; i = D[i]) { for (j = R[i]; j != i; j = R[j]) { D[U[j]] = D[j]; U[D[j]] = U[j]; S[Col[j]]--; } } } inline void Resume(int c) { int i,j; for (i = U[c]; i != c; i = U[i]) { for (j = L[i]; j != i; j = L[j]) { D[U[j]] = j; U[D[j]] = j; S[Col[j]]++; } } L[R[c]] = c; R[L[c]] = c; } inline bool solve(int dep) { int i,j,c; if (R[0] == 0) { step = dep; return true; } c = R[0]; for (i = R[0]; i != 0; i = R[i]) { if (S[i] < S[c]) c = i; } Remove(c); for (i = D[c]; i != c; i = D[i]) { ans[dep] = Row[i]; for (j = R[i]; j != i; j = R[j]) Remove(Col[j]); if (solve(dep+1)) return true; for (j = L[i]; j != i; j = L[j]) Resume(Col[j]); } Resume(c); return false; } } DLX; int main() { while (scanf("%s",s+1) && s[1] != ‘e‘) { cnt = 1; memset(mat,0,sizeof(mat)); for (i = 1; i <= 81; i++) { if (s[i] != ‘.‘) { mat[1][i] = 1; mat[1][81+(getRow(i)-1)*9+s[i]-‘0‘] = 1; mat[1][162+(getCol(i)-1)*9+s[i]-‘0‘] = 1; mat[1][243+(getGrid(i)-1)*9+s[i]-‘0‘] = 1; } else { for (j = 1; j <= 9; j++) { cnt++; mat[cnt][i] = 1; mat[cnt][81+(getRow(i)-1)*9+j] = 1; mat[cnt][162+(getCol(i)-1)*9+j] = 1; mat[cnt][243+(getGrid(i)-1)*9+j] = 1; a[cnt] = (info){i,j}; } } } DLX.init(cnt,324); for (i = 1; i <= cnt; i++) { for (j = 1; j <= 324; j++) { if (mat[i][j]) DLX.link(i,j); } } DLX.solve(0); for (i = 1; i < DLX.step; i++) s[a[DLX.ans[i]].pos] = ‘0‘ + a[DLX.ans[i]].val; for (i = 1; i <= 81; i++) printf("%c",s[i]); printf(" "); } return 0; }
以上是关于POJ 3074 Sudoku的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3074 Sudoku(Dancing Links)