poj 3074 DLX模板

// 题目链接 http://poj.org/problem?id=3074

 // 精确覆盖问题求解转载:https://www.cnblogs.com/grenet/p/3145800.html

// 把数独问题转换为精确覆盖问题转载:https://www.cnblogs.com/grenet/p/3163550.html

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 using namespace std;
  5 
  6 //const int INF = 1 << 30;
  7 const int maxn = 729;
  8 const int maxnode = 2916;
  9 const int maxnr = 729;
 10 
 11 //行编号从1开始,列编号为1~n,结点0是表头结点;结点1~n是各列顶部的虚拟结点
 12 struct DLX {
 13     int n, sz;//列数, 结点总数
 14     int S[maxn];//各列节点数
 15 
 16     int row[maxnode], col[maxnode];//各结点行列编号
 17     int L[maxnode], R[maxnode], U[maxnode], D[maxnode];//十字链表
 18 
 19     int ansd, ans[maxnr];//
 20 
 21     void init(int n) {//n是列数
 22         this->n = n;
 23 
 24         //虚拟结点
 25         for(int i = 0; i <= n; ++i) {
 26             U[i] = i;
 27             D[i] = i;
 28             L[i] = i-1;
 29             R[i] = i+1;
 30         }
 31         R[n] = 0; L[0] = n;
 32 
 33         sz = n + 1;
 34         memset(S, 0, sizeof(S));
 35     }
 36 
 37     void addRow(int r, vector<int> columns) {
 38         int first = sz;
 39         for(int i = 0; i != columns.size(); ++i) {
 40             int c = columns[i];
 41             L[sz] = sz-1; R[sz] = sz+1; D[sz] = c; U[sz] = U[c];
 42             D[U[c]] = sz; U[c] = sz;
 43             row[sz] = r; col[sz] = c;
 44             S[c]++; sz++;
 45         }
 46         R[sz-1] = first; L[first] = sz-1;
 47     }
 48     // 顺着链表A, 遍历除s外的其它元素
 49     #define FOR(i, A, s) for(int i = A[s]; i != s; i = A[i])
 50 
 51     void remove(int c) {
 52         L[R[c]] = L[c];
 53         R[L[c]] = R[c];
 54         FOR(i, D, c)
 55             FOR(j, R, i) {
 56                 U[D[j]] = U[j];
 57                 D[U[j]] = D[j];
 58                 --S[col[j]];
 59             }
 60     }
 61 
 62     void restore(int c) {
 63         FOR(i, U, c) 
 64             FOR(j, L, i) {
 65                 ++S[col[j]];
 66                 U[D[j]] = j;
 67                 D[U[j]] = j;
 68             }
 69         L[R[c]] = c;
 70         R[L[c]] = c;
 71     }
 72 
 73     // d为递归深度
 74     bool dfs(int d) {
 75         if(R[0] == 0) {  // 找到解
 76             ansd = d;    // 记录解的长度
 77             return true;
 78         }
 79         
 80         // 找s最小的列c
 81         int c = R[0];              // 第一个未删除的列
 82         FOR(i, R, 0) if(S[i] < S[c]) c = i;
 83 
 84         remove(c);                 // 删除c列
 85         FOR(i, D, c) {             // 用结点i所在的行覆盖第c列
 86             ans[d] = row[i];
 87             FOR(j, R, i) remove(col[j]);// 删除结点i所在行能覆盖的所有其它列
 88             if(dfs(d+1)) return true;
 89             FOR(j, L, i) restore(col[j]);// 恢复结点i所在行能覆盖的所有其它列
 90         }
 91         restore(c);                // 恢复第c列
 92 
 93         return false;
 94     }
 95 
 96     bool solve(vector<int>& v) {
 97         v.clear();
 98         if(!dfs(0)) return false;
 99         for(int i = 0; i != ansd; ++i) v.push_back(ans[i]);
100         return true;
101     }
102 };
103 
104 const int SLOT = 0;
105 const int ROW = 1;
106 const int COL = 2;
107 const int SUB = 3;
108 
109 inline int encode(int a, int b, int c) {
110     return a*81 + b*9 + c + 1;
111 }
112 
113 inline void decode(int code, int &a, int &b, int &c) {
114     code--;
115     c = code%9; code /= 9;
116     b = code%9; code /= 9;
117     a = code;
118 }
119 
120 DLX solver;
121 
122 int main() {
123     char str[81];
124     char puzzle[9][9];
125     while(scanf("%s", str) == 1 && strcmp(str, "end")) {
126         solver.init(324);
127         for(int i = 0; i != 9; ++i) {
128             for(int j = 0; j != 9; ++j) {
129                 puzzle[i][j] = str[i*9 + j];
130             }
131         }
132         for(int r = 0; r != 9; ++r) {
133             for(int c = 0; c != 9; ++c) {
134                 for(int v = 0; v != 9; ++v) {
135                     if(puzzle[r][c] == '.' || puzzle[r][c]-'0' == v+1) {
136                         vector<int> columns;
137                         columns.push_back(encode(SLOT, r, c));
138                         columns.push_back(encode(ROW, r, v));
139                         columns.push_back(encode(COL, c, v));
140                         columns.push_back(encode(SUB, (r/3)*3 + c/3, v));
141                         solver.addRow(encode(r, c, v), columns);
142                     }
143                 }
144             }
145         }
146         vector<int> ans;
147         solver.solve(ans);
148 
149         for(int i = 0; i != ans.size(); ++i) {
150             int r, c, v;
151             decode(ans[i], r, c, v);
152             puzzle[r][c] = '1'+v;
153         }
154         for(int i = 0; i != 9; ++i) {
155             for(int j = 0; j != 9; ++j) {
156                 printf("%c", puzzle[i][j]);
157             }
158         }
159         printf("\n");
160     }
161     return 0;
162 }

猜你喜欢

转载自www.cnblogs.com/pupil-xj/p/11618712.html