码迷,mamicode.com
首页 > 其他好文 > 详细

【POJ 3074】 Sudoku

时间:2018-07-04 15:12:02      阅读:348      评论:0      收藏:0      [点我收藏+]

标签:精确   string   amp   def   ring   覆盖   链接   scan   span   

【题目链接】

           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("\n");
        }
        
        return 0;
    
}

 

【POJ 3074】 Sudoku

标签:精确   string   amp   def   ring   覆盖   链接   scan   span   

原文地址:https://www.cnblogs.com/evenbao/p/9263156.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!