【POJ 3076】 Sudoku

【题目链接】

           http://poj.org/problem?id=3076

【算法】

          将数独问题转化为精确覆盖问题,用Dancing Links求解

【代码】

           

#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 100000

struct info
{
        int pos,val;
} a[MAXS];

int i,j,cnt;
int mat[5000][2000];
char s[300];

inline int getRow(int pos)
{
        return (pos - 1) / 16 + 1;        
}
inline int getCol(int pos)
{
        return (pos - 1) % 16 + 1;        
}
inline int getGrid(int pos)
{
        int x = getRow(pos),y = getCol(pos);
        return (x - 1) / 4 * 4 + (y - 1) / 4 + 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) != EOF)
        {
                cnt = 1;
                memset(mat,0,sizeof(mat));
                for (i = 1; i < 16; i++) scanf("%s",s+i*16+1);
                for (i = 1; i <= 256; i++)
                {
                        if (s[i] != '-')
                        {
                                mat[1][i] = 1;
                                mat[1][256+(getRow(i)-1)*16+s[i]-'A'+1] = 1;
                                mat[1][512+(getCol(i)-1)*16+s[i]-'A'+1] = 1;
                                mat[1][768+(getGrid(i)-1)*16+s[i]-'A'+1] = 1;
                        } else
                        {
                                for (j = 1; j <= 16; j++)
                                {
                                        cnt++;
                                        mat[cnt][i] = 1;
                                        mat[cnt][256+(getRow(i)-1)*16+j] = 1;
                                        mat[cnt][512+(getCol(i)-1)*16+j] = 1;
                                        mat[cnt][768+(getGrid(i)-1)*16+j] = 1;
                                        a[cnt] = (info){i,j};
                                }
                        }
                }
                DLX.init(cnt,1024);
                for (i = 1; i <= cnt; i++)
                {
                        for (j = 1; j <= 1024; 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] = 'A' + a[DLX.ans[i]].val - 1;
                for (i = 1; i <= 256; i++)
                {
                        printf("%c",s[i]);
                        if (i % 16 == 0) printf("
");
                }
                printf("
");
        }
        
        return 0;
    
}
原文地址:https://www.cnblogs.com/evenbao/p/9263489.html