zoukankan      html  css  js  c++  java
  • HDU 4069 数独

      好久没做题了,建图搞了好久…… 然后,判是否有多解的时候会把原来的答案覆盖掉…… 这里没注意,弄了一下午……

    代码:

      

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <string>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <map>
    #include <set>
    #include <functional>
    #include <cctype>
    #include <time.h>
    
    using namespace std;
    
    const int INF = 1<<30;
    const int MAXN = 9*9*4+5;
    const int MAXR = 9*9*9+5;
    const int MAXNODE = MAXN*MAXR+5;
    
    struct DLX {
    // 行编号从1开始,列编号为1~n,结点0是表头结点;结点1~n是各列顶部的虚拟结点
        int n, sz; // 列数,结点总数
        int S[MAXN]; //各列结点数
    
        int row[MAXNODE], col[MAXNODE]; //各结点行列编号
        int L[MAXNODE], R[MAXNODE], U[MAXNODE], D[MAXNODE]; //十字链表
    
        int ansd, ans[MAXR]; //
    
        void init(int n)  { //n是列数
            this->n = n;
    
            //虚拟结点
            for (int i = 0; i <= n; i++) {
                U[i] = i; D[i] = i; L[i] = i-1; R[i] = i+1;
            }
            R[n] = 0; L[0] = n;
            sz = n+1;
            memset(S, 0, sizeof(S));
        }
    
        void addRow(int r, vector<int> columns) {
            //这一行的第一个结点
            //行没有设头结点,每一行连成一个环形
            int first = sz;
            for (int i = 0; i < columns.size(); i++) {
                int c = columns[i];
                L[sz] = sz-1; R[sz] = sz+1; D[sz] = c; U[sz] = U[c];
                D[U[c]] = sz; U[c] = sz;
                row[sz] = r; col[sz] = c;
                S[c]++; sz++;
            }
            R[sz-1] = first; L[first] = sz-1;
        }
    
        //顺着链表A,遍历s外的其他元素
        #define FOR(i, A, s) for (int i = A[s]; i != s; i = A[i])
    
        void remove(int c) { //删除c列
            L[R[c]] = L[c]; R[L[c]] = R[c];
            for (int i = D[c]; i != c; i = D[i]) // 对于每一个c列不为0的所有行
                for (int j = R[i]; j != i; j = R[j]) { //删除这一整行
                    U[D[j]] = U[j]; D[U[j]] = D[j]; S[col[j]]--;
                }
        }
    
        void restore(int c) { //回连c列
            for (int i = U[c]; i != c; i = U[i])
                for (int j = L[i]; j != i; j = L[j]) {
                    U[D[j]] = j; D[U[j]] = j; S[col[j]]++;
                }
            L[R[c]] = c; R[L[c]] = c;
        }
    
        int flag;
    
        void dfs(int d) { //d为递归深度
            if (R[0] == 0) { //找到解
                ansd = d; //记录解的长度
                flag++;
                return ;
            }
    
            //找S最小的C列
            int c = R[0]; //第一个未删除的列
            for (int i = R[0]; i != 0; i = R[i]) if (S[i]<S[c]) c = i;
            remove(c); //删除第c列
            for (int i = D[c]; i != c; i = D[i]) { //用结点i所在的行覆盖第c列
                if (!flag) ans[d] = row[i];
                for (int j = R[i]; j != i; j = R[j]) remove(col[j]); //删除节结点i所在行覆盖第c列
                dfs(d+1);
                if (flag>1) return ;
                for (int j = L[i]; j != i; j = L[j]) restore(col[j]); // 恢复
            }
            restore(c); //恢复
        }
    
        int solve(vector<int> &v) {
            v.clear();
            flag = 0;
            dfs(0);
            for (int i = 0; i < ansd; i++) v.push_back(ans[i]);
            return flag;
        }
    };
    
    const int dir[4][2] = { {-1, 0}, {0, 1}, {1, 0}, {0, -1} };
    
    const int SLOT = 0;
    const int ROW = 1;
    const int COL = 2;
    const int SUB = 3;
    
    inline int encode(int a, int b, int c) { return a*81+b*9+c+1; }
    inline void decode(int code, int &a, int &b, int &c) {
        code--;
        c = code%9; code /= 9;
        b = code%9; code /= 9;
        a = code;
    }
    
    DLX solver;
    int Matrix[22][22];
    int belong[9][9];
    int cnt;
    
    vector<int> columns;
    
    void test() { int *p = 0; (*p) = 0; }
    
    void dfs(int r, int c, int num) {
        belong[r][c] = cnt;
        int t = Matrix[r][c]>>4;
        int nr, nc;
        for (int i = 0; i < 4; i++) if (!(t&(1<<i))) {
            nr = r+dir[i][0]; nc = c+dir[i][1];
            if (!(0<=nr&&nr<9)||!(0<=nc&&nc<9)||belong[nr][nc]!=-1) continue;
            dfs(nr, nc, num+1);
        }
    }
    
    void solve() {
        solver.init(9*9*4);
        for (int r = 0; r < 9; r++) {
            for (int c = 0; c < 9; c++) {
                Matrix[r][c] %= 16;
                for (int v = 1; v <= 9; v++) {
                    if (Matrix[r][c]!=0 && Matrix[r][c]!=v) continue;
                    columns.clear();
                    columns.push_back(encode(SLOT, r, c));
                    columns.push_back(encode(ROW, r, v-1));
                    columns.push_back(encode(COL, c, v-1));
                    columns.push_back(encode(SUB, belong[r][c], v-1));
                    solver.addRow(encode(r, c, v-1), columns);
                }
            }
        }
    
        int ans = solver.solve(columns);
        if (ans == 2) { puts("Multiple Solutions"); return; }
        if (ans == 0) { puts("No solution"); return; }
        for (int i = 0; i < columns.size(); i++) {
            int r, c, v;
            decode(columns[i], r, c, v);
            Matrix[r][c] = v+1;
        }
        for (int r = 0; r < 9; r++) {
            for (int c = 0; c < 9; c++) {
                printf("%d", Matrix[r][c]);
            }
            puts("");
        }
    }
    
    int main() {
        #ifdef Phantom01
            freopen("HDU4069.txt", "r", stdin);
    //        freopen("HDU4069.out", "w", stdout);
        #endif //Phantom01
    
        int T;
        scanf("%d", &T);
        for (int C = 1; C <= T; C++) {
            printf("Case %d:
    ", C);
            for (int i = 0; i < 9; i++)
                for (int j = 0; j < 9; j++)
                    scanf("%d", &Matrix[i][j]);
    
            for (int r = 0; r < 9; r++)
                for (int c = 0; c < 9; c++)
                    belong[r][c] = -1;
    
            cnt = 0;
            for (int r = 0; r < 9; r++) {
                for (int c = 0; c < 9; c++) if (belong[r][c]==-1){
                    dfs(r, c, 1);
                    cnt++;
                }
            }
            solve();
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    读取美团购
    获取enum的Description
    获取手机号码所在地
    手动添加XA/XD的端口和磁盘映射
    无法使用SQL Server Management Studio的找到Network Server
    [XenDesktop5.5]+HyperV上的Win7+VDA无法启用Aero效果
    傻瓜式设置WANem配置 (点对点网络设置)
    [XD5.5]如何关闭XD的Audio UDP通道
    使用TCP方式登陆OCS
    在Linux上建立文件夹指向在Win共享的文件夹
  • 原文地址:https://www.cnblogs.com/Phantom01/p/4117334.html
Copyright © 2011-2022 走看看