• 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("
    ");
    160     }
    161     return 0;
    162 }
  • 相关阅读:
    Ubuntu20安装docker
    ubuntu 下mysql 大小写问题
    Tensorflow-常见报错解决方案
    迁移学习(Transfer Learning)
    c#的托管代码和非托管代码的理解
    .net面试题升级版
    ADO.NET知识点
    支持“WeShopDb”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库
    .net 面试题
    6、zookeeper应用场景-分布式唯一ID
  • 原文地址:https://www.cnblogs.com/pupil-xj/p/11618712.html
Copyright © 2020-2023  润新知