• POJ 3074 3076 Sudoku(Dancing Links)


    题意:

    求解数独。

    思路:

    1. 如何用 dancing links 求解数独?其中的精确覆盖策略十分精妙,感叹之余只能膜拜 Knuth 了;

    2. 如何把数独问题分解成矩阵,假设是 9*9 数独问题,则分下面 4 种限制条件:

       a) 每一行元素不能重复;

       b) 每一列元素不能重复;

       c) 每个 3*3 矩阵元素不能重复;

       d) 每个格子只能存放一个数字;

    3. 达到上述 4 个条件之后就可以构造 01 方阵了,列表示对于元素的限制,行代表所有格子的选择。所以有 81 * 4 列(对应上面 4 个条件),有 81 * 9 行。

    5. 求解的要求是:选定其中的行,当且仅当把所有的列选择完毕之后,停止递归,当然要求每一列只有一个 1 存在。此时 Q 里面存放的就是一个可行解。

    6. 其中 S 数组里面存放的是每一列 1 的个数。按照 DLX 算法的要求,每次递归总选择 1 最少的列开始,这样能够有效的减少分支。因为最终只是寻找一个可行解就返回。

    7. Dancing Links 在下面 CSDN 链接的几篇博客比较清楚。简单描述下:

       a) 选定 1 最少的列,对其进行删除,同时删除此列上存在 1 的行。因为某个列只能选择一个 1 的缘故,所以选择了此列上某个 1 便不能选择其它 1;

       b) 选定删除列的某一行,删除此行上面存在 1 的列,即某一行达到了列所在的几个限制条件,理应对列进行删除。删除列时的操作同 a) 的操作;

       c) 如果所有的列都被删除了,则我们的任务完成,Q 中保存的即是我们曾经选中的行,即可行解。否则重复 a) 的操作或者进行回溯操作;

    http://www.cppblog.com/notonlysuccess/archive/2009/07/10/89701.aspx

    http://blog.csdn.net/mu399/article/details/7627763

    // 3074

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int INFS = 0x3fffffff;
    const int MAXC = 81 * 4;
    const int MAXR = 81 * 9;
    const int MAXN = MAXC * MAXR + 10;
    
    int U[MAXN], D[MAXN], L[MAXN], R[MAXN];
    int grid[MAXR+10][MAXC+10], col[MAXN], row[MAXN], S[MAXC+10], Q[MAXR+10], QC;
    
    void remove(int c) {
        L[R[c]] = L[c];
        R[L[c]] = R[c];
        for (int i = D[c]; i != c; i = D[i]) {
            for (int j = R[i]; j != i; j = R[j]) {
                U[D[j]] = U[j];
                D[U[j]] = D[j];
                S[col[j]] -= 1;
            }
        }
    }
    
    void resume(int c) {
        for (int i = U[c]; i != c; i = U[i]) {
            for (int j = L[i]; j != i; j = L[j]) {
                U[D[j]] = D[U[j]] = j;
                S[col[j]] += 1;
            }
        }
        R[L[c]] = L[R[c]] = c;
    }
    
    bool dfs() {
        if (R[0] == 0)
            return true;
    
        int mins = INFS, c = 0;
        for (int i = R[0]; i != 0; i = R[i]) {
            if (S[i] < mins)
                mins = S[i], c = i;
        }
        remove(c);
        for (int i = D[c]; i != c; i = D[i]) {
            for (int j = R[i]; j != i; j = R[j])
                remove(col[j]);
            Q[QC++] = row[i];
            if (dfs())
                return true;
            QC -= 1;
            for (int j = L[i]; j != i; j = L[j])
                resume(col[j]);
        }
        resume(c);
        return false;
    }
    
    void solve(int ans[]) {
        QC = 0;
        dfs();
        for (int i = 0; i < QC; i++)
            ans[(Q[i]-1)/9] = (Q[i] - 1) % 9 + 1;
    }
    
    void buildmatrix(char data[]) {
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                if (data[i*9+j] == '.') {
                    for (int k = 1; k <= 9; k++) {
                        int r = (i * 9 + j) * 9 + k;
                        int c1 = 81 * 0 + i * 9 + k;
                        int c2 = 81 * 1 + j * 9 + k;
                        int c3 = 81 * 2 + (i / 3 * 3 + j / 3) * 9 + k;
                        int c4 = 81 * 3 + i * 9 + j + 1;
                        grid[r][c1] = grid[r][c2] = grid[r][c3] = grid[r][c4] = 1;
                    }
                } else {
                    int k = data[i*9+j] - '0';
                    int r = (i * 9 + j) * 9 + k;
                    int c1 = 81 * 0 + i * 9 + k;
                    int c2 = 81 * 1 + j * 9 + k;
                    int c3 = 81 * 2 + (i / 3 * 3 + j / 3) * 9 + k;
                    int c4 = 81 * 3 + i * 9 + j + 1;
                    grid[r][c1] = grid[r][c2] = grid[r][c3] = grid[r][c4] = 1;
                }
            }
        }
    }
    
    void builddlx() {
        memset(S, 0, sizeof(S));
        for (int i = 1; i <= MAXC; i++) 
            R[i-1] = L[i+1] = U[i] = D[i] = i;
        R[MAXC] = L[1] = 0;
    
        int c = MAXC;
        for (int i = 1; i <= MAXR; i++) {
            int cflag = -1;
            for (int j = 1; j <= MAXC; j++) {
                if (grid[i][j] == 1) {
                    c += 1;
                    S[j] += 1;
    
                    row[c] = i;
                    col[c] = j;
                    U[c] = U[j];
                    D[c] = j;
                    D[U[j]] = c;
                    U[j] = c;
    
                    if (cflag == -1) {
                        R[c] = L[c] = c;
                        cflag = c;
                    } else {
                        L[c] = L[cflag];
                        R[c] = cflag;
                        R[L[c]] = c;
                        L[cflag] = c;
                    }
                }
            }
        }
    }
    
    bool initdata() {
        char data[100];
        scanf("%s", data);
    
        if (data[0] == 'e')
            return false;
    
        memset(grid, 0, sizeof(grid));
        buildmatrix(data);
        builddlx();
        return true;
    }
    
    int main() {
        while (initdata()) {
            int ans[100];
            solve(ans);
            for (int i = 0; i < 81; i++)
                printf("%d", ans[i]);
            printf("\n");
        }
        return 0;
    }

    // 3076
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int INFS = 0x3fffffff;
    const int MAXC = 16 * 16 * 4;
    const int MAXR = 16 * 16 * 16;
    const int MAXN = MAXC * MAXR + 10;
    
    int U[MAXN], D[MAXN], L[MAXN], R[MAXN];
    int grid[MAXR+10][MAXC+10], col[MAXN], row[MAXN], S[MAXC+10], Q[MAXR+10], QC;
    char data[20][20];
    
    void remove(int c) {
        L[R[c]] = L[c];
        R[L[c]] = R[c];
        for (int i = D[c]; i != c; i = D[i]) {
            for (int j = R[i]; j != i; j = R[j]) {
                U[D[j]] = U[j];
                D[U[j]] = D[j];
                S[col[j]] -= 1;
            }
        }
    }
    
    void resume(int c) {
        for (int i = U[c]; i != c; i = U[i]) {
            for (int j = L[i]; j != i; j = L[j]) {
                U[D[j]] = D[U[j]] = j;
                S[col[j]] += 1;
            }
        }
        R[L[c]] = L[R[c]] = c;
    }
    
    bool dfs() {
        if (R[0] == 0)
            return true;
    
        int mins = INFS, c = 0;
        for (int i = R[0]; i != 0; i = R[i]) {
            if (S[i] < mins)
                mins = S[i], c = i;
        }
        remove(c);
        for (int i = D[c]; i != c; i = D[i]) {
            for (int j = R[i]; j != i; j = R[j])
                remove(col[j]);
            Q[QC++] = row[i];
            if (dfs())
                return true;
            QC -= 1;
            for (int j = L[i]; j != i; j = L[j])
                resume(col[j]);
        }
        resume(c);
        return false;
    }
    
    void solve(char ans[]) {
        QC = 0;
        dfs();
        for (int i = 0; i < QC; i++)
            ans[(Q[i]-1)/16] = (Q[i] - 1) % 16 + 'A';
    }
    
    void buildmatrix() {
        for (int i = 0; i < 16; i++) {
            for (int j = 0; j < 16; j++) {
                if (data[i][j] == '-') {
                    for (int k = 1; k <= 16; k++) {
                        int r = (i * 16 + j) * 16 + k;
                        int c1 = 256 * 0 + i * 16 + k;
                        int c2 = 256 * 1 + j * 16 + k;
                        int c3 = 256 * 2 + (i / 4 * 4 + j / 4) * 16 + k;
                        int c4 = 256 * 3 + i * 16 + j + 1;
                        grid[r][c1] = grid[r][c2] = grid[r][c3] = grid[r][c4] = 1;
                    }
                } else {
                    int k = data[i][j] - 'A' + 1;
                    int r = (i * 16 + j) * 16 + k;
                    int c1 = 256 * 0 + i * 16 + k;
                    int c2 = 256 * 1 + j * 16 + k;
                    int c3 = 256 * 2 + (i / 4 * 4 + j / 4) * 16 + k;
                    int c4 = 256 * 3 + i * 16 + j + 1;
                    grid[r][c1] = grid[r][c2] = grid[r][c3] = grid[r][c4] = 1;
                }
            }
        }
    }
    
    void builddlx() {
        memset(S, 0, sizeof(S));
        for (int i = 1; i <= MAXC; i++) 
            R[i-1] = L[i+1] = U[i] = D[i] = i;
        R[MAXC] = L[1] = 0;
    
        int c = MAXC;
        for (int i = 1; i <= MAXR; i++) {
            int cflag = -1;
            for (int j = 1; j <= MAXC; j++) {
                if (grid[i][j] == 1) {
                    c += 1;
                    S[j] += 1;
    
                    row[c] = i;
                    col[c] = j;
                    U[c] = U[j];
                    D[c] = j;
                    D[U[j]] = c;
                    U[j] = c;
    
                    if (cflag == -1) {
                        R[c] = L[c] = c;
                        cflag = c;
                    } else {
                        L[c] = L[cflag];
                        R[c] = cflag;
                        R[L[c]] = c;
                        L[cflag] = c;
                    }
                }
            }
        }
    }
    
    bool initdata() {
        while (scanf("%s", data[0]) != EOF)
        {
            for (int i = 1; i < 16; i++)
                scanf("%s", data[i]);
    
            memset(grid, 0, sizeof(grid));
            buildmatrix();
            builddlx();
            return true ;
        }
        return false;
    }
    
    int main() {
        while (initdata()) {
            char ans[300];
            solve(ans);
            for (int i = 0; i < 16; i++) {
                for (int j = 0; j < 16; j++) {
                    printf("%c", ans[i*16+j]);
                }
                printf("\n");
            }
            printf("\n");
        }
        return 0;
    }

    3239 1077
  • 相关阅读:
    并发的简单介绍1
    UITableView (4): 在TableView中移动cell和Section 从TableView中删除cell和section 添加系统默认刷新控件
    UITableView (3):显示cell上的菜单
    TableView(2)
    UITableView (1)
    在 Interface Builder 中配置自动布局的约束
    Velocity 的工作原理
    ORA-01858: a non-numeric character was found where a numeric was expected
    Java 8:不要再用循环了
    Lambda表达式
  • 原文地址:https://www.cnblogs.com/kedebug/p/2974555.html
Copyright © 2020-2023  润新知