• POJ 2676 Sudoku (搜索,Dancing Links)


    题目:

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

    题意:

    数独,每行1-9,每列1-9,每3*3小格1-9,填数,不能重复

    方法:Dancing Links(16ms)或者DFS暴搜(400-900ms)

    Dancing Links(DLX) 是为了解决矩阵精确覆盖问题的算法,算法效率非常高

    使用DLX解决的问题必须转化为矩阵精确覆盖问题:

    1、DLX详解:

    http://wenku.baidu.com/view/d8f13dc45fbfc77da269b126.html

    2、转化方法:

    非常详细的讲解:http://www.cnblogs.com/grenet/p/3163550.html

    约束1:每个格子只能填一个数:dlx.Link(t, encode(0, i, j));

    约束2:每行需1-9:dlx.Link(t, encode(1, i, k - 1));

    约束3:每列需1-9:dlx.Link(t, encode(2, j, k - 1));

    约束4:每3*3格子需1-9:dlx.Link(t, encode(3, (i / 3) * 3 + j / 3, k - 1));

     1 void build()
     2 {
     3     for (int i = 0; i < 9; i++)
     4         for (int j = 0; j < 9; j++)
     5             for (int k = 1; k <= 9; k++)
     6                 if (mtx[i][j] == '0' || mtx[i][j] == k + '0')
     7                 {
     8                     int t = encode(i, j, k - 1);
     9                     dlx.Link(t, encode(0, i, j));
    10                     dlx.Link(t, encode(1, i, k - 1));
    11                     dlx.Link(t, encode(2, j, k - 1));
    12                     dlx.Link(t, encode(3, (i / 3) * 3 + j / 3, k - 1));
    13                 }
    14 }

    DLX模板(转自kuangbin(http://www.cnblogs.com/kuangbin/p/3752854.html)):

     1 const int maxnode = 100010;
     2 const int MaxM = 1010;
     3 const int MaxN = 1010;
     4 struct DLX
     5 {
     6     int n, m, size;
     7     int U[maxnode], D[maxnode], R[maxnode], L[maxnode], Row[maxnode], Col[maxnode];
     8     int H[MaxN], S[MaxM];
     9     int ansd, ans[MaxN];
    10     void init(int _n, int _m)
    11     {
    12         n = _n;
    13         m = _m;
    14         for (int i = 0; i <= m; i++)
    15         {
    16             S[i] = 0;
    17             U[i] = D[i] = i;
    18             L[i] = i - 1;
    19             R[i] = i + 1;
    20         }
    21         R[m] = 0; L[0] = m;
    22         size = m;
    23         for (int i = 1; i <= n; i++)
    24             H[i] = -1;
    25     }
    26     void Link(int r, int c)
    27     {
    28         ++S[Col[++size] = c];
    29         Row[size] = r;
    30         D[size] = D[c];
    31         U[D[c]] = size;
    32         U[size] = c;
    33         D[c] = size;
    34         if (H[r] < 0)H[r] = L[size] = R[size] = size;
    35         else
    36         {
    37             R[size] = R[H[r]];
    38             L[R[H[r]]] = size;
    39             L[size] = H[r];
    40             R[H[r]] = size;
    41         }
    42     }
    43     void remove(int c)
    44     {
    45         L[R[c]] = L[c]; R[L[c]] = R[c];
    46         for (int i = D[c]; i != c; i = D[i])
    47             for (int j = R[i]; j != i; j = R[j])
    48             {
    49                 U[D[j]] = U[j];
    50                 D[U[j]] = D[j];
    51                 --S[Col[j]];
    52             }
    53     }
    54     void resume(int c)
    55     {
    56         for (int i = U[c]; i != c; i = U[i])
    57             for (int j = L[i]; j != i; j = L[j])
    58                 ++S[Col[U[D[j]] = D[U[j]] = j]];
    59         L[R[c]] = R[L[c]] = c;
    60     }
    61     //d为递归深度
    62     bool Dance(int d)
    63     {
    64         if (R[0] == 0)
    65         {
    66             ansd = d;
    67             return true;
    68         }
    69         int c = R[0];
    70         for (int i = R[0]; i != 0; i = R[i])
    71             if (S[i] < S[c])
    72                 c = i;
    73         remove(c);
    74         for (int i = D[c]; i != c; i = D[i])
    75         {
    76             ans[d] = Row[i];
    77             for (int j = R[i]; j != i; j = R[j])remove(Col[j]);
    78             if (Dance(d + 1))return true;
    79             for (int j = L[i]; j != i; j = L[j])resume(Col[j]);
    80         }
    81         resume(c);
    82         return false;
    83     }
    84 };
    DLX模板(from kuangbin)

    代码:

      1 /********************************************
      2 *ACM Solutions
      3 *
      4 *@Title:
      5 *@Version: 1.0
      6 *@Time: 2014-xx-xx
      7 *@Solution: http://www.cnblogs.com/xysmlx/p/xxxxxxx.html
      8 *
      9 *@Author: xysmlx(Lingxiao Ma)
     10 *@Blog: http://www.cnblogs.com/xysmlx
     11 *@EMail: xysmlx@163.com
     12 *
     13 *Copyright (C) 2011-2015 xysmlx(Lingxiao Ma)
     14 ********************************************/
     15 // #pragma comment(linker, "/STACK:102400000,102400000")
     16 #include <cstdio>
     17 #include <iostream>
     18 #include <cstring>
     19 #include <string>
     20 #include <cmath>
     21 #include <set>
     22 #include <list>
     23 #include <map>
     24 #include <iterator>
     25 #include <cstdlib>
     26 #include <vector>
     27 #include <queue>
     28 #include <stack>
     29 #include <algorithm>
     30 #include <functional>
     31 using namespace std;
     32 typedef long long LL;
     33 #define pb push_back
     34 #define ROUND(x) round(x)
     35 #define FLOOR(x) floor(x)
     36 #define CEIL(x) ceil(x)
     37 const int maxn = 0;
     38 const int maxm = 0;
     39 const int inf = 0x3f3f3f3f;
     40 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
     41 const double INF = 1e30;
     42 const double eps = 1e-6;
     43 const int P[4] = {0, 0, -1, 1};
     44 const int Q[4] = {1, -1, 0, 0};
     45 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
     46 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};
     47 
     48 const int maxnode = 100010;
     49 const int MaxM = 1010;
     50 const int MaxN = 1010;
     51 struct DLX
     52 {
     53     int n, m, size;
     54     int U[maxnode], D[maxnode], R[maxnode], L[maxnode], Row[maxnode], Col[maxnode];
     55     int H[MaxN], S[MaxM];
     56     int ansd, ans[MaxN];
     57     void init(int _n, int _m)
     58     {
     59         n = _n;
     60         m = _m;
     61         for (int i = 0; i <= m; i++)
     62         {
     63             S[i] = 0;
     64             U[i] = D[i] = i;
     65             L[i] = i - 1;
     66             R[i] = i + 1;
     67         }
     68         R[m] = 0; L[0] = m;
     69         size = m;
     70         memset(H, -1, sizeof(H));
     71         // for (int i = 1; i <= n; i++)
     72         //     H[i] = -1;
     73     }
     74     void Link(int r, int c)
     75     {
     76         ++S[Col[++size] = c];
     77         Row[size] = r;
     78         D[size] = D[c];
     79         U[D[c]] = size;
     80         U[size] = c;
     81         D[c] = size;
     82         if (H[r] < 0)H[r] = L[size] = R[size] = size;
     83         else
     84         {
     85             R[size] = R[H[r]];
     86             L[R[H[r]]] = size;
     87             L[size] = H[r];
     88             R[H[r]] = size;
     89         }
     90     }
     91     void remove(int c)
     92     {
     93         L[R[c]] = L[c]; R[L[c]] = R[c];
     94         for (int i = D[c]; i != c; i = D[i])
     95             for (int j = R[i]; j != i; j = R[j])
     96             {
     97                 U[D[j]] = U[j];
     98                 D[U[j]] = D[j];
     99                 --S[Col[j]];
    100             }
    101     }
    102     void resume(int c)
    103     {
    104         for (int i = U[c]; i != c; i = U[i])
    105             for (int j = L[i]; j != i; j = L[j])
    106                 ++S[Col[U[D[j]] = D[U[j]] = j]];
    107         L[R[c]] = R[L[c]] = c;
    108     }
    109     //d为递归深度
    110     bool Dance(int d)
    111     {
    112         if (R[0] == 0)
    113         {
    114             ansd = d;
    115             return true;
    116         }
    117         int c = R[0];
    118         for (int i = R[0]; i != 0; i = R[i])
    119             if (S[i] < S[c])
    120                 c = i;
    121         remove(c);
    122         for (int i = D[c]; i != c; i = D[i])
    123         {
    124             ans[d] = Row[i];
    125             for (int j = R[i]; j != i; j = R[j])remove(Col[j]);
    126             if (Dance(d + 1))return true;
    127             for (int j = L[i]; j != i; j = L[j])resume(Col[j]);
    128         }
    129         resume(c);
    130         return false;
    131     }
    132 } dlx;
    133 
    134 int kase;
    135 int n, m;
    136 char mtx[20][20];
    137 void init()
    138 {
    139     n = 9, m = 9;
    140     kase++;
    141     dlx.init(1, 324);
    142 }
    143 void input()
    144 {
    145     for (int i = 0; i < 9; i++)
    146         scanf("%s", mtx[i]);
    147 }
    148 void debug()
    149 {
    150     //
    151 }
    152 int encode(int a, int b, int c)
    153 {
    154     return a * 81 + b * 9 + c + 1;
    155 }
    156 void decode(int code, int &a, int &b, int &c)
    157 {
    158     code--;
    159     c = code % 9;
    160     code /= 9;
    161     b = code % 9;
    162     code /= 9;
    163     a = code;
    164 }
    165 void build()
    166 {
    167     for (int i = 0; i < 9; i++)
    168         for (int j = 0; j < 9; j++)
    169             for (int k = 1; k <= 9; k++)
    170                 if (mtx[i][j] == '0' || mtx[i][j] == k + '0')
    171                 {
    172                     int t = encode(i, j, k - 1);
    173                     dlx.Link(t, encode(0, i, j));
    174                     dlx.Link(t, encode(1, i, k - 1));
    175                     dlx.Link(t, encode(2, j, k - 1));
    176                     dlx.Link(t, encode(3, (i / 3) * 3 + j / 3, k - 1));
    177                 }
    178 }
    179 void solve()
    180 {
    181     build();
    182     dlx.Dance(0);
    183     for (int i = 0; i < dlx.ansd; i++)
    184     {
    185         int r, c, k;
    186         decode(dlx.ans[i], r, c, k);
    187         mtx[r][c] = k + '1';
    188     }
    189 }
    190 void output()
    191 {
    192     for (int i = 0; i < 9; i++)
    193         printf("%s
    ", mtx[i]);
    194 }
    195 int main()
    196 {
    197     // int size = 256 << 20; // 256MB
    198     // char *p = (char *)malloc(size) + size;
    199     // __asm__("movl %0, %%esp
    " :: "r"(p));
    200 
    201     // std::ios_base::sync_with_stdio(false);
    202 #ifdef xysmlx
    203     freopen("in.cpp", "r", stdin);
    204 #endif
    205 
    206     kase = 0;
    207     int T;
    208     scanf("%d", &T);
    209     while (T--)
    210     {
    211         init();
    212         input();
    213         solve();
    214         output();
    215     }
    216     return 0;
    217 }
    POJ 2676
  • 相关阅读:
    祥解使用 SQL Server 2005/2008 发送数据库邮件
    将Virtual Server 2005 的虚拟硬盘(VHD)文件复制到HyperV
    Win2008 64位 iis7 环境下安装Discuz!NT
    seo
    找了好办天才找到的asp生成图片学习一下
    1.1 开发背景 (学习图书连载csdn
    我眼中的C# 3.0
    google编程
    反射之反思
    我要减肥
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3951267.html
Copyright © 2020-2023  润新知