【HDOJ】3909 Sudoku

DLX的应用,基本题,注意maxnode开大点儿。

  1 /* 3909 */
  2 #include <iostream>
  3 #include <string>
  4 #include <map>
  5 #include <queue>
  6 #include <set>
  7 #include <stack>
  8 #include <vector>
  9 #include <deque>
 10 #include <algorithm>
 11 #include <cstdio>
 12 #include <cmath>
 13 #include <ctime>
 14 #include <cstring>
 15 #include <climits>
 16 #include <cctype>
 17 #include <cassert>
 18 #include <functional>
 19 #include <iterator>
 20 #include <iomanip>
 21 using namespace std;
 22 //#pragma comment(linker,"/STACK:102400000,1024000")
 23
 24 #define sti                set<int>
 25 #define stpii            set<pair<int, int> >
 26 #define mpii            map<int,int>
 27 #define vi                vector<int>
 28 #define pii                pair<int,int>
 29 #define vpii            vector<pair<int,int> >
 30 #define rep(i, a, n)     for (int i=a;i<n;++i)
 31 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
 32 #define clr                clear
 33 #define pb                 push_back
 34 #define mp                 make_pair
 35 #define fir                first
 36 #define sec                second
 37 #define all(x)             (x).begin(),(x).end()
 38 #define SZ(x)             ((int)(x).size())
 39 #define lson            l, mid, rt<<1
 40 #define rson            mid+1, r, rt<<1|1
 41
 42 typedef struct DLX {
 43     static const int maxc = 4*16*16+5;
 44     static const int maxr = 16*16*16+5;
 45     static const int maxnode = 16*16*16*5+5;
 46
 47     int n, sz;
 48     int S[maxc];
 49
 50     int row[maxnode], col[maxnode];
 51     int L[maxnode], R[maxnode], U[maxnode], D[maxnode];
 52
 53     int ansd, cnt, ans[maxr], ans_[maxr];
 54
 55     void init(int n_) {
 56         cnt = 0;
 57         n = n_;
 58
 59         rep(i, 0, n+1) {
 60             L[i] = i-1;
 61             R[i] = i+1;
 62             U[i] = i;
 63             D[i] = i;
 64         }
 65
 66         L[0] = n;
 67         R[n] = 0;
 68
 69         sz = n+1;
 70         memset(S, 0, sizeof(S));
 71     }
 72
 73     void addRow(int r, vi columns) {
 74         int first = sz;
 75         int size = SZ(columns);
 76
 77         rep(i, 0, size) {
 78             int c = columns[i];
 79
 80             L[sz] = sz-1;
 81             R[sz] = sz+1;
 82
 83             D[sz] = c;
 84             U[sz] = U[c];
 85             D[U[c]] = sz;
 86             U[c] = sz;
 87
 88             row[sz] = r;
 89             col[sz] = c;
 90
 91             ++S[c];
 92             ++sz;
 93         }
 94
 95         R[sz - 1] = first;
 96         L[first] = sz - 1;
 97     }
 98
 99     void remove(int c) {
100         L[R[c]] = L[c];
101         R[L[c]] = R[c];
102         for (int i=D[c]; i!=c; i=D[i]) {
103             for (int j=R[i]; j!=i; j=R[j]) {
104                 U[D[j]] = U[j];
105                 D[U[j]] = D[j];
106                 --S[col[j]];
107             }
108         }
109     }
110
111     void restore(int c) {
112         L[R[c]] = c;
113         R[L[c]] = c;
114         for (int i=D[c]; i!=c; i=D[i]) {
115             for (int j=R[i]; j!=i; j=R[j]) {
116                 U[D[j]] = j;
117                 D[U[j]] = j;
118                 ++S[col[j]];
119             }
120         }
121     }
122
123     bool dfs(int d) {
124         if (R[0] == 0) {
125             ansd = d;
126             ++cnt;
127             rep(i, 0, ansd)
128                 ans_[i] = ans[i];
129             return cnt>1;
130         }
131
132         int c = R[0];
133         for (int i=R[0]; i!=0; i=R[i]) {
134             if (S[i] < S[c])
135                 c = i;
136         }
137
138         remove(c);
139         for (int i=D[c]; i!=c; i=D[i]) {
140             ans[d] = row[i];
141             for (int j=R[i]; j!=i; j=R[j]) {
142                 remove(col[j]);
143             }
144             if (dfs(d + 1))    return true;
145             for (int j=L[i]; j!=i; j=L[j]) {
146                 restore(col[j]);
147             }
148         }
149         restore(c);
150
151         return false;
152     }
153
154     void solve(vi& v) {
155
156         dfs(0);
157
158         if (cnt == 1) {
159             v.clr();
160             rep(i, 0, ansd)
161                 v.pb(ans_[i]);
162         }
163     }
164
165 } DLX;
166
167 DLX solver;
168 int n, n2, n2n2;
169 const int maxl = 20;
170 char M[maxl][maxl], M_[maxl][maxl];
171 const int SLOT     = 0;
172 const int ROW      = 1;
173 const int COL    = 2;
174 const int SUB    = 3;
175
176 int encode(int a, int b, int c) {
177     return a*n2n2 + b*n2 + c + 1;
178 }
179
180 void decode(int code, int& a, int& b, int& c) {
181     --code;
182     c = code % n2;
183     code /= n2;
184     b = code % n2;
185     code /= n2;
186     a = code;
187 }
188
189 int getVal(char c) {
190     if (c>=‘0‘ && c<=‘9‘)    return c-‘1‘;
191     return c-‘A‘+9;
192 }
193
194 int getChar(int val) {
195     if (val < 9)    return val+‘1‘;
196     return val-9+‘A‘;
197 }
198
199 void init() {
200     n2 = n * n;
201     n2n2 = n2 * n2;
202 }
203
204 void solve(vi& ans) {
205     solver.init(4 * n2n2);
206
207     rep(r, 0, n2) {
208         rep(c, 0, n2) {
209             rep(v, 0, n2) {
210                 if (M[r][c]==‘.‘ || v==getVal(M[r][c])) {
211                     vi columns;
212                     columns.pb(encode(SLOT, r, c));
213                     columns.pb(encode(ROW, r, v));
214                     columns.pb(encode(COL, c, v));
215                     columns.pb(encode(SUB, r/n*n+c/n, v));
216                     solver.addRow(encode(r, c, v), columns);
217                 }
218             }
219         }
220     }
221
222     solver.solve(ans);
223 }
224
225 int main() {
226     ios::sync_with_stdio(false);
227     #ifndef ONLINE_JUDGE
228         freopen("data.in", "r", stdin);
229         freopen("data.out", "w", stdout);
230     #endif
231
232     vi ans, tmp;
233
234     while (scanf("%d", &n) != EOF) {
235         init();
236         rep(i, 0, n2)
237             scanf("%s", M[i]);
238
239         solve(ans);
240
241         if (solver.cnt == 0) {
242             puts("No Solution");
243             continue;
244         } else if (solver.cnt > 1) {
245             puts("Multiple Solutions");
246             continue;
247         }
248
249         // check if is minimal
250         bool flag = true;
251
252         rep(r, 0, n2) {
253             rep(c, 0, n2) {
254                 if (M[r][c] != ‘.‘) {
255                     char ch = M[r][c];
256                     M[r][c] = ‘.‘;
257                     solve(tmp);
258                     M[r][c] = ch;
259                     if (solver.cnt <= 1) {
260                         flag = false;
261                         goto _output;
262                     }
263                 }
264             }
265         }
266
267         _output:
268         if (flag) {
269             int sz = SZ(ans);
270             rep(i, 0, sz) {
271                 int r, c, v;
272                 decode(ans[i], r, c, v);
273                 char ch = getChar(v);
274                 M[r][c] = ch;
275             }
276
277             rep(i, 0, n2)
278                 puts(M[i]);
279         } else {
280             puts("Not Minimal");
281         }
282     }
283
284     #ifndef ONLINE_JUDGE
285         printf("time = %d.\n", (int)clock());
286     #endif
287
288     return 0;
289 }
时间: 2024-08-01 10:30:37

【HDOJ】3909 Sudoku的相关文章

【HDOJ】4956 Poor Hanamichi

基本数学题一道,看错位数,当成大数减做了,而且还把方向看反了.所求为最接近l的值. 1 #include <cstdio> 2 3 int f(__int64 x) { 4 int i, sum; 5 6 i = sum = 0; 7 while (x) { 8 if (i & 1) 9 sum -= x%10; 10 else 11 sum += x%10; 12 ++i; 13 x/=10; 14 } 15 return sum; 16 } 17 18 int main() { 1

【HDOJ】1099 Lottery

题意超难懂,实则一道概率论的题目.求P(n).P(n) = n*(1+1/2+1/3+1/4+...+1/n).结果如果可以除尽则表示为整数,否则表示为假分数. 1 #include <cstdio> 2 #include <cstring> 3 4 #define MAXN 25 5 6 __int64 buf[MAXN]; 7 8 __int64 gcd(__int64 a, __int64 b) { 9 if (b == 0) return a; 10 else return

【HDOJ】2844 Coins

完全背包. 1 #include <stdio.h> 2 #include <string.h> 3 4 int a[105], c[105]; 5 int n, m; 6 int dp[100005]; 7 8 int mymax(int a, int b) { 9 return a>b ? a:b; 10 } 11 12 void CompletePack(int c) { 13 int i; 14 15 for (i=c; i<=m; ++i) 16 dp[i]

【HDOJ】3509 Buge&#39;s Fibonacci Number Problem

快速矩阵幂,系数矩阵由多个二项分布组成.第1列是(0,(a+b)^k)第2列是(0,(a+b)^(k-1),0)第3列是(0,(a+b)^(k-2),0,0)以此类推. 1 /* 3509 */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #incl

【HDOJ】1818 It&#39;s not a Bug, It&#39;s a Feature!

状态压缩+优先级bfs. 1 /* 1818 */ 2 #include <iostream> 3 #include <queue> 4 #include <cstdio> 5 #include <cstring> 6 #include <cstdlib> 7 #include <algorithm> 8 using namespace std; 9 10 #define MAXM 105 11 12 typedef struct {

【HDOJ】2424 Gary&#39;s Calculator

大数乘法加法,直接java A了. 1 import java.util.Scanner; 2 import java.math.BigInteger; 3 4 public class Main { 5 public static void main(String[] args) { 6 Scanner cin = new Scanner(System.in); 7 int n; 8 int i, j, k, tmp; 9 int top; 10 boolean flag; 11 int t

【HDOJ】2425 Hiking Trip

优先级队列+BFS. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 7 #define MAXN 25 8 9 typedef struct node_st { 10 int x, y, t; 11 node_st() {} 12 node_st(int xx, int yy, int tt)

【HDOJ】1686 Oulipo

kmp算法. 1 #include <cstdio> 2 #include <cstring> 3 4 char src[10005], des[1000005]; 5 int next[10005], total; 6 7 void kmp(char des[], char src[]){ 8 int ld = strlen(des); 9 int ls = strlen(src); 10 int i, j; 11 12 total = i = j = 0; 13 while (

【HDOJ】2795 Billboard

线段树.注意h范围(小于等于n). 1 #include <stdio.h> 2 #include <string.h> 3 4 #define MAXN 200005 5 #define lson l, mid, rt<<1 6 #define rson mid+1, r, rt<<1|1 7 #define mymax(x, y) (x>y) ? x:y 8 9 int nums[MAXN<<2]; 10 int h, w; 11 12