zoukankan      html  css  js  c++  java
  • 1317. Sudoku

    解题技巧:1.数独每个格子记录自身还能填的数字,每次寻找能填数字数最少的格子填充数字。

         2.使用“禁用计数”的方式,记录每个格子某个数字被禁用的次数,以便脱离禁用后恢复可填性。

    #include <cstdio>
    #include <cstring>
    #include <set>
    #include <vector>
    using std::set;
    using std::vector;
    
    struct Elem {
        int num;
        set<int> lefts;
    };
    
    set<int> LEFTS;
    
    const int maxn = 9;
    char charMap[maxn][maxn+1];
    Elem Map[maxn][maxn];
    
    int ans[maxn][maxn];
    int count;
    int f[maxn][maxn][maxn + 1];
    
    
    struct Cor {
        int r, c;
        Cor(int r_ = 0, int c_ = 0) : r(r_), c(c_) {}
        bool operator<(const Cor &cor) const {
            return (r < cor.r) || (r == cor.r && c < cor.c);
        }
    };
    
    set<Cor> unfills;
    
    
    void init() {
        for (int i = 0; i < maxn; ++i) {
            for (int j = 0; j < maxn; ++j) {
                Map[i][j].num = 0;
                Map[i][j].lefts.insert(LEFTS.begin(), LEFTS.end());
            }
        }
        for (int i = 0; i < maxn; ++i) {
            for (int j = 0; j < maxn; ++j) {
                for (int k = 0; k < maxn; ++k) {
                    f[i][j][k + 1] = 0;
                }
            }
        }
        count = 0;
        unfills.clear();
    }
    
    void input() {
        for (int i = 0; i < maxn; ++i) {
            scanf("%s", charMap[i]);
        }
    }
    
    void transform() {
        for (int i = 0; i < maxn; ++i) {
            for (int j = 0; charMap[i][j] != ''; ++j) {
                if (charMap[i][j] != '_') {
                    Map[i][j].num = charMap[i][j] - '0';
                } else {
                    unfills.insert(Cor(i, j));
                }
            }
        }
    }
    
    void setting(int r, int c, int num) {
        Map[r][c].num = num;
        for (int i = 0; i < maxn; ++i) {
            Map[r][i].lefts.erase(num);
            ++f[r][i][num];
            Map[i][c].lefts.erase(num);
            ++f[i][c][num];
        }
        int beginr = r / 3 * 3;
        int beginc = c / 3 * 3;
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                Map[i + beginr][j + beginc].lefts.erase(num);
                ++f[i + beginr][j + beginc][num];
            }
        }
    }
    
    void resume(int r, int c, int num) {
        Map[r][c].num = 0;
        for (int i = 0; i < maxn; ++i) {
            if (--f[r][i][num] == 0) Map[r][i].lefts.insert(num);
            if (--f[i][c][num] == 0) Map[i][c].lefts.insert(num);
        }
        int beginr = r / 3 * 3;
        int beginc = c / 3 * 3;
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                if (--f[i+beginr][j+beginc][num] == 0) Map[i + beginr][j + beginc].lefts.insert(num);
            }
        }
    }
    
    void predeal() {
        for (int i = 0; i < maxn; ++i) {
            for (int j = 0; j < maxn; ++j) {
                if (Map[i][j].num != 0) {
                    setting(i, j, Map[i][j].num);
                }
            }
        }
    }
    
    void dfs() {
        if (unfills.empty()) {
            // 达到一种目的状态
            ++count;
            if (count > 1) return;
            for (int i = 0; i < maxn; ++i) {
                for (int j = 0; j < maxn; ++j) {
                    ans[i][j] = Map[i][j].num;
                }
            }
        } else {
            // 遍历unfills,寻找最小的
            set<Cor>::iterator iter = unfills.begin(), target = unfills.begin();
            while (iter != unfills.end()) {
                const Cor &cor1 = *iter;
                const Cor &cor2 = *target;
                if (Map[cor1.r][cor1.c].lefts.size() < Map[cor2.r][cor2.c].lefts.size()) {
                    target = iter;
                }
                ++iter;
            }
            Cor cor = *target;
            unfills.erase(target);
            set<int> _lefts(Map[cor.r][cor.c].lefts);   // 
            set<int>::iterator iter1 = _lefts.begin();
            while (iter1 != _lefts.end()) {
                int num = *iter1;
                setting(cor.r, cor.c, num);
                dfs();
                resume(cor.r, cor.c, num);
                ++iter1;
            }
            unfills.insert(cor);
        }
    }
    
    int main() {
        for (int i = 1; i <= 9; ++i) LEFTS.insert(i);
        int t;
        scanf("%d", &t);
        for (int tt = 1; tt <= t; ++tt) {
            // 初始化
            init();
            // 输入
            input();
            // 转化
            transform();
            // 预处理
            predeal();
            // 深搜
            dfs();
    
            if (count == 0) {
                printf("Puzzle %d has no solution
    ", tt);
            } else if (count == 1) {
                printf("Puzzle %d solution is
    ", tt);
                for (int i = 0; i < maxn; ++i) {
                    for (int j = 0; j < maxn; ++j) {
                        printf("%d", ans[i][j]);
                    }
                    printf("
    ");
                }
            } else if (count > 1) {
                printf("Puzzle %d has %d solutions
    ", tt, count);
            }
            if (tt != t) printf("
    ");
        }
    
        return 0;
    }
    

      

  • 相关阅读:
    django + dropzone.js 上传文件
    随机知识点---后续整理
    Python项目在Jenkins中的自动化测试实践(语法检查、单元测试,coverage(代码覆盖率)、自动打包)
    my read / zikao / nanjingdaxue
    OS + CentOS kernel parameter
    network / Wireshark
    使用docker部署springBoot并且yml配置文件不打包到jar中
    idea + springBoot项目配置远程调试
    MySql优化建议
    springBoot事务失效导致批量插入性能巨幅降低
  • 原文地址:https://www.cnblogs.com/mchcylh/p/5104938.html
Copyright © 2011-2022 走看看