POJ 3074 Sudoku (DLX)

Sudoku
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u
Submit  Status  Practice  POJ 3074
Appoint description: System Crawler  (2015-04-18)

Description

In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

.2738..1.
.1...6735
.......29
3.5692.8.
.........
.6.1745.3
64.......
9518...7.
.8..6534.

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




用dancing links解数独,DLX专题的终极目标,手机上的数独玩了两天后终于A了,等下把记录用这个程序刷一遍,想象下小伙伴看到我最高难度下的耗时记录的表情,啊哈哈~~
难点在于怎么建立模型,一共有9行,每行有9个数字,所以就是9 * 9,同理,列也是9 * 9,小格子也是有9个,每个也是9个数字,所以也是9 * 9,另外整个图有9 * 9 = 81的格子。所以要覆盖的列就是 9 * 9 + 9 * 9 + 9 * 9 + 81。至于行,一共有81个格子,每个格子有9种取法,所以就有81 * 9行,行和列相乘就是开的数组的大小。还有个剪枝要注意下,如果某个格子的数字已经给出,那么这一行,这一列,这一个小格子,就没必要再填这个数了,不剪枝的话会T。
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <string>
  5 #include <cstdlib>
  6 #include <cmath>
  7 #include <map>
  8 #include <cctype>
  9 using    namespace    std;
 10 
 11 const    int    HEAD = 0;
 12 const    int    SIZE = (81 * 9) * (81 * 4);
 13 const    int    COL = 81 * 4;
 14 int    U[SIZE],D[SIZE],L[SIZE],R[SIZE],S[SIZE],C[SIZE],N[SIZE],P_H[SIZE],P_C[SIZE];
 15 int    COUNT;
 16 int    TEMP[100][100];
 17 bool    VIS_I[15][15],VIS_J[15][15],VIS_G[15][15];
 18 struct    Node
 19 {
 20     int    i;
 21     int    j;
 22     int    num;
 23 }ANS[100];
 24 
 25 void    ini(void);
 26 void    link(int,int,int,int,int,int,int);
 27 bool    dancing(int);
 28 void    remove(int);
 29 void    resume(int);
 30 void    debug(int);
 31 int    main(void)
 32 {
 33     char    s[1000];
 34     while(scanf(" %s",s + 1) && strcmp(s + 1,"end"))
 35     {
 36         ini();
 37         for(int i = 1;i <= 9;i ++)
 38             for(int j = 1;j <= 9;j ++)
 39             {
 40                 int    k = s[(i - 1) * 9 + j];
 41                 int    c_1,c_2,c_3,c_4;
 42                 if(k != '.')
 43                 {
 44                     VIS_I[i][k - '0'] = VIS_J[j][k - '0'] = true;
 45                     VIS_G[(i - 1) / 3 * 3 + (j - 1) / 3 + 1][k - '0'] = true;
 46                     c_1 = 81 * 0 + (i - 1) * 9 + k - '0';
 47                     c_2 = 81 * 1 + (j - 1) * 9 + k - '0';
 48                     c_3 = 81 * 2 + ((i - 1) / 3 * 3 + (j - 1) / 3) * 9 + k - '0';
 49                     c_4 = 81 * 3 + (i - 1) * 9 + j;
 50                     link(c_1,c_2,c_3,c_4,k - '0',i,j);
 51                 }
 52             }
 53 
 54         for(int i = 1;i <= 9;i ++)
 55             for(int j = 1;j <= 9;j ++)
 56             {
 57                 if(s[(i - 1) * 9 + j] != '.')
 58                     continue;
 59                 int    c_1,c_2,c_3,c_4;
 60                 for(int k = 1;k <= 9;k ++)
 61                 {
 62                     if(VIS_I[i][k] || VIS_J[j][k] || 
 63                             VIS_G[(i - 1) / 3 * 3 + (j - 1) / 3 + 1][k])
 64                         continue;
 65                     c_1 = 81 * 0 + (i - 1) * 9 + k;
 66                     c_2 = 81 * 1 + (j - 1) * 9 + k;
 67                     c_3 = 81 * 2 + ((i - 1) / 3 * 3 + (j - 1) / 3) * 9 + k;
 68                     c_4 = 81 * 3 + (i - 1) * 9 + j;
 69                     link(c_1,c_2,c_3,c_4,k,i,j);
 70                 }
 71             }
 72         dancing(0);
 73     }
 74 
 75     return    0;
 76 }
 77 
 78 void    ini(void)
 79 {
 80     L[HEAD] = COL;
 81     R[HEAD] = 1;
 82     for(int    i = 1;i <= COL;i ++)
 83     {
 84         L[i] = i - 1;
 85         R[i] = i + 1;
 86         U[i] = D[i] = C[i] = i;
 87         S[i] = 0;
 88     }
 89     R[COL] = HEAD;
 90 
 91     fill(&VIS_I[0][0],&VIS_I[12][12],false);
 92     fill(&VIS_J[0][0],&VIS_J[12][12],false);
 93     fill(&VIS_G[0][0],&VIS_G[12][12],false);
 94     COUNT = COL + 1;
 95 }
 96 
 97 void    link(int c_1,int c_2,int c_3,int c_4,int num,int r,int c)
 98 {
 99     int    first = COUNT;
100     int    col;
101 
102     for(int i = 0;i < 4;i ++)
103     {
104         switch(i)
105         {
106             case    0:col = c_1;break;
107             case    1:col = c_2;break;
108             case    2:col = c_3;break;
109             case    3:col = c_4;break;
110         }
111 
112         L[COUNT] = COUNT - 1;
113         R[COUNT] = COUNT + 1;
114         U[COUNT] = U[col];
115         D[COUNT] = col;
116 
117         D[U[col]] = COUNT;
118         U[col] = COUNT;
119         C[COUNT] = col;
120         N[COUNT] = num;
121         P_H[COUNT] = r;
122         P_C[COUNT] = c;
123         S[col] ++;
124         COUNT ++;
125     }
126     L[first] = COUNT - 1;
127     R[COUNT - 1] = first;
128 }
129 
130 bool    dancing(int k)
131 {
132     if(R[HEAD] == HEAD)
133     {
134         for(int i = 0;i < k;i ++)
135             TEMP[ANS[i].i][ANS[i].j] = ANS[i].num;
136         int    count = 0;
137         for(int i = 1;i <= 9;i ++)
138             for(int j = 1;j <= 9;j ++)
139                 printf("%d",TEMP[i][j]);
140         puts("");
141         return    true;
142     }
143 
144     int    c = R[HEAD];
145     for(int i = R[HEAD];i != HEAD;i = R[i])
146         if(S[c] > S[i])
147             c = i;
148 
149     remove(c);
150     for(int i = D[c];i != c;i = D[i])
151     {
152         ANS[k].i = P_H[i];
153         ANS[k].j = P_C[i];
154         ANS[k].num = N[i];
155         for(int j = R[i];j != i;j = R[j])
156             remove(C[j]);
157         if(dancing(k + 1))
158             return    true;
159         for(int j = L[i];j != i;j = L[j])
160             resume(C[j]);
161     }
162     resume(c);
163 
164     return    false;
165 }
166 
167 void    remove(int c)
168 {
169     L[R[c]] = L[c];
170     R[L[c]] = R[c];
171     for(int i = D[c];i != c;i = D[i])
172         for(int j = R[i];j != i;j = R[j])
173         {
174             D[U[j]] = D[j];
175             U[D[j]] = U[j];
176             S[C[j]] --;
177         }
178 }
179 
180 void    resume(int c)
181 {
182     L[R[c]] = c;
183     R[L[c]] = c;
184     for(int i = D[c];i != c;i = D[i])
185         for(int j = L[i];j != i;j = L[j])
186         {
187             D[U[j]] = j;
188             U[D[j]] = j;
189             S[C[j]] ++;
190         }
191 }

 

转载于:https://www.cnblogs.com/xz816111/p/4450237.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值