• POJ3074 Sudoku(lowbit优化搜索)


    In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

    . 2 7 3 8 . . 1 .
    . 1 . . . 6 7 3 5
    . . . . . . . 2 9
    3 . 5 6 9 2 . 8 .
    . . . . . . . . .
    . 6 . 1 7 3 5 . 3
    6 4 . . . . . . .
    9 5 1 8 . . . 7 .
    . 8 . . 6 5 3 4 .
    Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.

    输入
    The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.

    输出
    For each test case, print a line representing the completed Sudoku puzzle.

    样例输入
    .2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
    ......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
    end
    样例输出
    527389416819426735436751829375692184194538267268174593643217958951843672782965341
    416837529982465371735129468571298643293746185864351297647913852359682714128574936
    来源
    Stanford Local 2006

    题解:
    这里使用了lowbit来优化当前的方案,存入二进制数后可以用Lowbit搜索每一位。
    所以这说不定就是除了某d开头算法外数独较快的解法了吧。

    #include <bits/stdc++.h>
    #define lowbit(x) (x & (-x))
    using namespace std;
    char ch[12][12];
    int hang[12], lie[12], gong[12], cnt[1200], num[1200], tot;
    int get(int x, int y) { return (x / 3) * 3 + y / 3; }
    void flip(int x, int y, int z) {
        hang[x] ^= (1 << z);
        lie[y] ^= (1 << z);
        gong[get(x, y)] ^= (1 << z);
        return;
    }
    bool dfs(int now) {
        if (!now)
            return 1;
        int mn = 10, x, y;
        for (int i = 0; i < 9; i++)
            for (int j = 0; j < 9; j++) {
                if (ch[i][j] != '.')
                    continue;
                int val = hang[i] & lie[j] & gong[get(i, j)];
                if (!val)
                    return 0; //矛盾,回退
                if (cnt[val] < mn) {
                    mn = cnt[val];
                    x = i, y = j;
                }
            }
        int val = hang[x] & lie[y] & gong[get(x, y)];
        for (int i = val; i; i -= lowbit(i)) {
            int which = num[lowbit(i)];
            ch[x][y] = '1' + which;
            flip(x, y, which);
            if (dfs(now - 1))
                return 1;
            flip(x, y, which);
            ch[x][y] = '.';
        }
        return 0;
    }
    char yyh[12000];
    signed main() {
        for (int i = 0; i < (1 << 9); i++)
            for (int j = i; j; j -= lowbit(j))
                cnt[i]++; //有几个1
        for (int i = 0; i < 9; i++)
            num[1 << i] = i;
        while (scanf("%s", yyh) && yyh[0] != 'e') {
            for (int i = 0; i < 9; i++)
                for (int j = 0; j < 9; j++)
                    ch[i][j] = yyh[i * 9 + j];
            for(int i=0;i<9;i++) hang[i]=lie[i]=gong[i]=(1<<9)-1;
            tot=0;
            for (int i = 0; i < 9; i++)
                for (int j = 0; j < 9; j++)
                    if (ch[i][j]!='.') flip(i,j,ch[i][j]-'1');
                    else tot++;
            dfs(tot);
            for(int i=0;i<9;i++) for(int j=0;j<9;j++) cout<<ch[i][j];
            puts("");
        }
        return 0;
    }
    
  • 相关阅读:
    Win10/UWP开发-Ink墨迹书写
    Win10/UWP 让你的App使用上扫描仪
    Win10/UWP新特性—Drag&Drop 拖出元素到其他App
    UWP/Win10新特性系列—Drag&Drop 拖动打开文件
    1、WIN2D学习记录(win2d实现JS雨天效果)
    Windows 通用应用尝试开发 “51单片机汇编”总结
    D2.Reactjs 操作事件、状态改变、路由
    D1.1.利用npm(webpack)构建基本reactJS项目
    UWP 动画系列之模仿网易云音乐动画
    字符设备驱动之Led驱动学习记录
  • 原文地址:https://www.cnblogs.com/wky32768/p/10750778.html
Copyright © 2020-2023  润新知