• UVALive 2659 数独 DLX模板


    建图:

      从1到16枚举所有的行、列上放的数。

    代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <algorithm>
      7 #include <string>
      8 #include <queue>
      9 #include <stack>
     10 #include <vector>
     11 #include <map>
     12 #include <set>
     13 #include <functional>
     14 #include <cctype>
     15 #include <time.h>
     16 
     17 using namespace std;
     18 
     19 const int INF = 1<<30;
     20 const int MAXN = 1055;
     21 const int MAXNODE = 16555;
     22 const int MAXR = 1055;
     23 
     24 struct DLX {
     25 // 行编号从1开始,列编号为1~n,结点0是表头结点;结点1~n是各列顶部的虚拟结点
     26     int n, sz; // 列数,结点总数
     27     int S[MAXN]; //各列结点数
     28 
     29     int row[MAXNODE], col[MAXNODE]; //各结点行列编号
     30     int L[MAXNODE], R[MAXNODE], U[MAXNODE], D[MAXNODE]; //十字链表
     31 
     32     int ansd, ans[MAXR]; //
     33 
     34     void init(int n)  { //n是列数
     35         this->n = n;
     36 
     37         //虚拟结点
     38         for (int i = 0; i <= n; i++) {
     39             U[i] = i; D[i] = i; L[i] = i-1; R[i] = i+1;
     40         }
     41         R[n] = 0; L[0] = n;
     42         sz = n+1;
     43         memset(S, 0, sizeof(S));
     44     }
     45 
     46     void addRow(int r, vector<int> columns) {
     47         //这一行的第一个结点
     48         //行没有设头结点,每一行连成一个环形
     49         int first = sz;
     50         for (int i = 0; i < columns.size(); i++) {
     51             int c = columns[i];
     52             L[sz] = sz-1; R[sz] = sz+1; D[sz] = c; U[sz] = U[c];
     53             D[U[c]] = sz; U[c] = sz;
     54             row[sz] = r; col[sz] = c;
     55             S[c]++; sz++;
     56         }
     57         R[sz-1] = first; L[first] = sz-1;
     58     }
     59 
     60     //顺着链表A,遍历s外的其他元素
     61     #define FOR(i, A, s) for (int i = A[s]; i != s; i = A[i])
     62 
     63     void remove(int c) { //删除c列
     64         L[R[c]] = L[c]; R[L[c]] = R[c];
     65         for (int i = D[c]; i != c; i = D[i]) // 对于每一个c列不为0的所有行
     66             for (int j = R[i]; j != i; j = R[j]) { //删除这一整行
     67                 U[D[j]] = U[j]; D[U[j]] = D[j]; S[col[j]]--;
     68             }
     69     }
     70 
     71     void restore(int c) { //回连c列
     72         for (int i = U[c]; i != c; i = U[i])
     73             for (int j = L[i]; j != i; j = L[j]) {
     74                 U[D[j]] = j; D[U[j]] = j; S[col[j]]++;
     75             }
     76         L[R[c]] = c; R[L[c]] = c;
     77     }
     78 
     79     bool dfs(int d) { //d为递归深度
     80         if (R[0] == 0) { //找到解
     81             ansd = d; //记录解的长度
     82             return true;
     83         }
     84 
     85         //找S最小的C列
     86         int c = R[0]; //第一个未删除的列
     87         for (int i = R[0]; i != 0; i = R[i]) if (S[i]<S[c]) c = i;
     88 
     89         remove(c); //删除第c列
     90         for (int i = D[c]; i != c; i = D[i]) { //用结点i所在的行覆盖第c列
     91             ans[d] = row[i];
     92             for (int j = R[i]; j != i; j = R[j]) remove(col[j]); //删除节结点i所在行覆盖第c列
     93             if (dfs(d+1)) return true;
     94             for (int j = L[i]; j != i; j = L[j]) restore(col[j]); // 恢复
     95         }
     96         restore(c); //恢复
     97         return false;
     98     }
     99 
    100     bool solve(vector<int> &v) {
    101         v.clear();
    102         if(!dfs(0)) return false;
    103         for (int i = 0; i < ansd; i++) v.push_back(ans[i]);
    104         return true;
    105     }
    106 };
    107 
    108 const int SLOT = 0;
    109 const int ROW = 1;
    110 const int COL = 2;
    111 const int SUB = 3;
    112 
    113 inline int encode(int a, int b, int c) {
    114     return a*256 + b*16 + c + 1;
    115 }
    116 
    117 inline void decode(int code, int &a, int &b, int &c) {
    118     code--;
    119     c = code%16; code /= 16;
    120     b = code%16; code /= 16;
    121     a = code;
    122 }
    123 
    124 char puzzle[16][20];
    125 
    126 bool read() {
    127     for (int i = 0; i < 16; i++)
    128         if (scanf("%s", puzzle[i])!=1) return false;
    129     return true;
    130 }
    131 
    132 DLX solver;
    133 
    134 int main() {
    135     #ifdef Phantom01
    136         freopen("LA2659.txt", "r", stdin);
    137     #endif //Phantom01
    138 
    139     int T= 0;
    140 
    141     while (read()) {
    142         if (T!=0) puts(""); T++;
    143         solver.init(1024);
    144         for (int r = 0; r < 16; r++)
    145             for (int c = 0; c < 16; c++)
    146                 for (int v = 0; v < 16; v++)
    147                     if (puzzle[r][c]=='-'|| puzzle[r][c]=='A'+v) {
    148                         vector<int> columns;
    149                         columns.push_back(encode(SLOT, r, c));
    150                         columns.push_back(encode(ROW, r, v));
    151                         columns.push_back(encode(COL, c, v));
    152                         columns.push_back(encode(SUB, (r/4)*4+c/4, v));
    153                         solver.addRow(encode(r, c, v), columns);
    154                     }
    155         vector<int> ans;
    156         if (!solver.solve(ans)) while (1) ;
    157 
    158         for (int i = 0; i < ans.size(); i++) {
    159             int r, c, v;
    160             decode(ans[i], r, c, v);
    161             puzzle[r][c] = 'A'+v;
    162         }
    163         for (int i = 0; i < 16; i++) {
    164             printf("%s
    ", puzzle[i]);
    165         }
    166     }
    167 
    168     return 0;
    169 }
    View Code
  • 相关阅读:
    php常见细节错误
    php+jquery注册实例
    yii2添加自定义字段
    yii2开启session
    yii2中textarea中的默认值设置
    yii2.0分页
    yii2多语言
    mysql中查询值为NULL的记录
    yii Html中的a标签使用
    yii2顶部导航使用
  • 原文地址:https://www.cnblogs.com/Phantom01/p/4002320.html
Copyright © 2020-2023  润新知