• AcWing 166. 数独


    题目地址 https://www.acwing.com/problem/content/description/168/

    题目描述

    数独是一种传统益智游戏,你需要把一个9 × 9的数独补充完整,使得图中每行、每列、每个3 × 3的九宫格内数字1~9均恰好出现一次。

    请编写一个程序填写数独。

    输入格式
    输入包含多组测试用例。

    每个测试用例占一行,包含81个字符,代表数独的81个格内数据(顺序总体由上到下,同行由左到右)。

    每个字符都是一个数字(1-9)或一个”.”(表示尚未填充)。

    您可以假设输入中的每个谜题都只有一个解决方案。

    文件结尾处为包含单词“end”的单行,表示输入结束。

    输出格式
    每个测试用例,输出一行数据,代表填充完全后的数独。

    样例

    输入样例:
    .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

    法1
    时间卡的比较紧,搜索上做了许多优化

    1 进行可填写数据的筛选.由于数独本身的性质,1~9同一数字不能在同一行 同一列 同一九宫格出现两次以上。
    我开始计划是开一个 9*9的数组记录每个格子可能出现的数字.每次确认填写一个数字 就更新同行同列同九宫格里的记录
    但是这样的话,每次填写一个数字及需要更新 一行9个 一列9个 和九宫格九格的数据。共27个数据。
    YXC大佬的代码 使用的 行记录一个 列记录一个 九宫格记录一个 这样只需要更新三个数据即可

    2 优化填写格子的策略,每个格子可填写的数据比较少的优先选取。 这也是剪枝的一种.
    代码见

     //找到可选方案数最少的空格
        int minv = 10;
        int x, y;
        for(int i = 0;i < N;i++)
            for(int j = 0;j < N;j++)
                if (str[i*9+j] == '.') {
                    int t = ones[get(i, j)];
                    if (t < minv) {
                        minv = t;
                        x = i, y = j;
                    }
                }

    3 一些其他小技巧,使用位来记录该空格可填写那些数字
    000000001 表示可填写1
    000000010 表示可填写2
    000000100 表示可填写3
    000000101 表示可填写1和3
    ......
    x = 000000111 表示可填写1 2 3。 如果我们当前选择填写2 那么只要 x - (1<<(2-1))就可以把填写2的表示去除了
    代码里不是2-1 而是 可填写的数字的字母的实际值与 ‘1’的差值

    4 判断是否是统一九宫格 采用 x/3==i/3 y/3 == j/3

    还有其他一些小技巧 欢迎一起讨论

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <set>
      4 
      5 using namespace std;
      6 
      7 const int N = 9;
      8 
      9 int row[N], col[N],cell[3][3];
     10 
     11 char str[100];
     12 
     13 int ones[1 << N],map[1<<N];
     14 
     15 inline int lowbit(int x) {
     16     return x & -x;
     17 }
     18 
     19 void init()
     20 {
     21     for (int i = 0; i < N; i++) row[i] = col[i] = (1 << N) - 1;
     22     for (int i = 0; i < 3; i++)
     23         for (int j = 0; j < 3; j++)
     24             cell[i][j] = (1 << N) - 1;
     25 }
     26 
     27 inline int get(int x, int y)
     28 {
     29     return row[x] & col[y] & cell[x / 3][y / 3];
     30 
     31 }
     32 
     33 bool dfs(int cnt)
     34 {
     35     if (!cnt) return true;
     36 
     37     //找到可选方案数最少的空格
     38     int minv = 10;
     39     int x, y;
     40     for(int i = 0;i < N;i++)
     41         for(int j = 0;j < N;j++)
     42             if (str[i*9+j] == '.') {
     43                 int t = ones[get(i, j)];
     44                 if (t < minv) {
     45                     minv = t;
     46                     x = i, y = j;
     47                 }
     48             }
     49 
     50     for (int i = get(x, y); i; i -= lowbit(i)) {
     51         int t = map[lowbit(i)];
     52 
     53         //修改状态
     54         row[x] -= 1 << t;
     55         col[y] -= 1 << t;
     56         cell[x / 3][y / 3] -= 1 << t;
     57         str[x * 9 + y] = '1' + t;
     58         if (dfs(cnt - 1)) return true;
     59 
     60         //回复现场
     61         row[x] += 1 << t;
     62         col[y] += 1 << t;
     63         cell[x / 3][y / 3] += 1 << t;
     64         str[x * 9 + y] = '.';
     65     }
     66 
     67 
     68     return false;
     69 }
     70 
     71 int main()
     72 {
     73     for (int i = 0; i < N; i++) map[1 << i] = i;
     74     for (int i = 0; i < 1 << N; i++) {
     75         int s = 0;
     76         for(int j = i; j;j -= lowbit(j)) s++;
     77         ones[i] = s; //i的二进制表示中有s个1
     78     }
     79 
     80     while (cin >> str, str[0] != 'e') {
     81         init();
     82         int cnt = 0;
     83         for(int i =0,k = 0;i < N;i++)
     84             for(int j = 0; j < N;j++,k++)
     85                 if (str[k] != '.') {
     86                     int t = str[k] - '1';
     87                     row[i] -= 1 << t;
     88                     col[j] -= 1 << t;
     89                     cell[i / 3][j / 3] -= 1 << t;
     90                 }
     91                 else {
     92                     cnt++;
     93                 }
     94 
     95         dfs(cnt);
     96         cout << str << endl;
     97     }
     98 
     99     return 0;
    100 
    101 }
    102 
    103 作者:defddr
    104 链接:https://www.acwing.com/solution/AcWing/content/2294/
    105 来源:AcWing
    106 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
    View Code
      1 // 11111111.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
      2 //
      3 
      4 #include <iostream>
      5 #include <map>
      6 #include <vector>
      7 #include <string>
      8 #include <stdio.h>
      9 
     10 using namespace std;
     11 
     12 
     13 
     14 /*
     15 .2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
     16 ......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
     17 end
     18 */
     19 
     20 
     21 const int N = 9;
     22 
     23 int map1[1 << N];
     24 int Xarr[N];
     25 int Yarr[N];
     26 int SameXYArr[N / 3][N / 3];
     27 
     28 int ones[1 << N], map[1 << N];
     29 
     30 char str[100];
     31 
     32 void Init()
     33 {
     34     for (int i = 0; i < N; i++) {
     35         Xarr[i] = (1 << N) - 1;
     36         Yarr[i] = (1 << N) - 1;
     37         map1[1 << i] = i;
     38     }
     39 
     40     for (int i = 0; i < N / 3; i++) {
     41         for (int j = 0; j < N / 3; j++) {
     42             SameXYArr[i][j] = (1 << N) - 1;
     43         }
     44     }
     45 }
     46 
     47 inline int lowbit(int x) {
     48     return x & -x;
     49 }
     50 
     51 inline int get(int x, int y)
     52 {
     53          return Xarr[x] & Yarr[y] & SameXYArr[x / 3][y / 3];
     54 }
     55 
     56 bool Dfs(int count, char str[])
     57 {
     58     if (!count) return true;
     59 
     60     int minv = 10;
     61     int minx = -1; int miny = -1;
     62 
     63     for (int x = 0; x < 9; x++) {
     64         for (int y = 0; y < 9; y++)
     65         {
     66             if (str[x * 9 + y] == '.') {
     67                 int t = ones[get(x,y)];
     68                 
     69                 if (t < minv) {
     70                     minv = t;
     71                     minx = x;
     72                     miny = y;
     73                 }
     74             }
     75         }
     76     }
     77 
     78     if (0 == minv)
     79         return false;
     80 
     81     int tryNums = get(minx, miny);
     82     
     83 
     84     while (tryNums != 0) {
     85         int trynum = map1[lowbit(tryNums)];
     86         
     87         Xarr[minx] -= 1 << trynum;
     88         Yarr[miny] -= 1 << trynum;
     89         SameXYArr[minx / 3][miny / 3] -= 1 << trynum;
     90         str[minx * 9 + miny] = '1' + trynum;
     91 
     92         if (Dfs(count - 1, str))  return true;
     93 
     94         //回复现场
     95         Xarr[minx] += 1 << trynum;
     96         Yarr[miny] += 1 << trynum;
     97         SameXYArr[minx / 3][miny / 3] += 1 << trynum;
     98         str[minx * 9 + miny] = '.';
     99 
    100         tryNums -= lowbit(tryNums);
    101     }
    102 
    103     return false;
    104 }
    105 
    106 void Do(char str[])
    107 {
    108     Init();
    109     int count = 0;
    110     for (int i = 0; i < 9; i++) {
    111         for (int j = 0; j < 9; j++) {
    112             if (str[i * 9 + j] != '.') {
    113                 int idx = 1 << (str[i * 9 + j] - '1');
    114                 Xarr[i] -= idx;
    115                 Yarr[j] -= idx;
    116                 SameXYArr[i / 3][j / 3] -= idx;
    117             }
    118             else {
    119                 count++;
    120             }
    121         }
    122     }
    123 
    124     Dfs(count, str);
    125     cout << str << endl;
    126 
    127     return;
    128 }
    129 
    130 
    131 int main()
    132 {
    133     ios::sync_with_stdio(false);
    134 
    135     for (int i = 0; i < N; i++) map1[1 << i] = i;
    136          for (int i = 0; i < 1 << N; i++) {
    137                  int s = 0;
    138                  for (int j = i; j; j -= lowbit(j)) s++;
    139                  ones[i] = s; //i的二进制表示中有s个1
    140         
    141     }
    142     
    143         while (cin >> str, str[0] != 'e') {
    144             //s = ".2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.";
    145 
    146             Do(str);
    147         }
    148         
    149     
    150 }
    View Code
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    UI是一个状态机
    WPF : Binding的3个属性: Source, RelativeSource, ElementName
    业务驱动设计
    WPF : 对Collection要注意重用子控件
    WPF : UserControl的Initialized事件不会触发
    mvc3上传图片
    MVC3.0自定义视图引擎(切换皮肤)
    ASP.NET MVC 多语言解决方案
    键盘键位表
    Silverlight之IsolatedStorageSettings对象
  • 原文地址:https://www.cnblogs.com/itdef/p/10943355.html
Copyright © 2020-2023  润新知