利用计算机程序快速得到9*9大小数独的解法

利用计算机程序快速得到9*9大小数独的解法对于9∗99*99∗9大小的数独游戏,我们可以使用回溯法求得其正确的解,但是,一般的回溯法实现这个过程保证不了时间复杂度,所以我们可以利用二进制压缩的方法来优化其过程。具体思路如下:明确数独的约束:相同一行不能出现重复的数相同一列不能出现重复的数同一宫内不能出现重复的数定义row[i]row[i]row[i]数组代表,第i,ji,ji,j位置,在iii行哪些数被占用,用二进制111表示没有被占用,000表示被占用那么最开始row[i]row[i]row[i]=111111

对于 9 ∗ 9 9*9 9∗9 大小的数独游戏,我们可以使用回溯法求得其正确的解,但是,一般的回溯法实现这个过程保证不了时间复杂度,所以我们可以利用二进制压缩的方法来优化其过程。

具体思路如下:

明确数独的约束:

  • 相同一行不能出现重复的数
  • 相同一列不能出现重复的数
  • 同一宫内不能出现重复的数

定义 r o w [ i ] row[i] row[i]数组代表,第 i , j i,j i,j位置,在 i i i 行哪些数被占用,用二进制 1 1 1 表示没有被占用, 0 0 0 表示被占用那么最开始 r o w [ i ] row[i] row[i] = 111111111 111111111 111111111,表示行没有数被占用。

定义 c o l [ j ] col[j] col[j]数组代表,第 i , j i,j i,j位置,第 j j j 列哪些数被占用,用二进制 1 1 1 表示没有被占用, 0 0 0 表示被占用,那么最开始 c o l [ i ] col[i] col[i] = 111111111 111111111 111111111,表示列没有数被占用。

定义 c e l l [ i / 3 ] [ j / 3 ] cell[i/3][j/3] cell[i/3][j/3]数组代表,第 i , j i,j i,j 格所在的宫中那些数被占用,用二进制 1 1 1 表示没有被占用, 0 0 0 表示被占用,那么最开始 c e l l [ i / 3 ] [ j / 3 ] cell[i/3][j/3] cell[i/3][j/3] = 111111111 111111111 111111111,表示宫中没有数被占用。

然后我们需要初始化上面三个数组,因为一开始的数独游戏位置被一些数占用了,那么这些数的位置就会影响 r o w [ i ] , c o l [ j ] , c e l l [ i ] [ j ] row[i],col[j],cell[i][j] row[i],col[j],cell[i][j]的二进制数,我们需要把相应的数,在二进制数的响应位改变成0,表示这个数在此列或行或宫被占用了。

然后我们利用位运算&对三个数组进行&,就可以得到三个数组都没有被占用的数,然后从其中挑选数,进行回溯法即可得到数独的解。

注意要熟悉: l o w b i t ( ) lowbit() lowbit()的用法,是取二进制数第一次出现 1 1 1时的大小,例如 100100 100100 100100,这个数的 l o w b i t ( ) lowbit() lowbit()就是 100 100 100,在这个程序中他用来取&后的数字的二进制可用数是多少,这个可用数我们也提前预处理,映射到了 m a p [ ] map[] map[]数组里,然后这个还有一个贪心策略,即当可用数越少答案就越确定,我们用 o n e s [ ] ones[] ones[]数组记录一下所有可出现状态的1的数量,1的数量少代表当前位置越确定,这个可以对程序执行很大的优化。

下面以一个数独游戏为例:
被解决的数独游戏:
在这里插入图片描述

程序跑出的解:
输入的时候空位置用.代替即可
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可执行代码:

#include <algorithm>
#include <iostream>
using namespace std;
const int N = 9;
int row[N], col[N], cell[3][3], ones[1 << N], map[1 << N], cnt;
char s[N][N];
inline int lowbit(int x) { 
   
  return (x & -x);
}
inline void init() { 
   
  for (int i = 0; i < N; i++)
    row[i] = col[i] = (1 << N) - 1;
  for (int i = 0; i < 3; i++)
    for (int j = 0; j < 3; j++)
      cell[i][j] = (1 << N) - 1;
}
inline int get(int x, int y) { 
   
  return row[x] & col[y] & cell[x / 3][y / 3];
}
bool dfs(int cnt) { 
   
  if (!cnt)
    return true;
  int x, y, mav = 10;
  for (int i = 0; i < N; i++) { 
   
    for (int j = 0; j < N; j++) { 
   
      if (s[i][j] == '.') { 
   
        int t = ones[get(i, j)];
        if (mav > t) { 
   
          mav = t;
          x = i, y = j;
        }
      }
    }
  }
  for (int i = get(x, y); i; i -= lowbit(i)) { 
   
    int t = map[lowbit(i)];
    row[x] -= 1 << t;
    col[y] -= 1 << t;
    cell[x / 3][y / 3] -= 1 << t;
    s[x][y] = '1' + t;
    if (dfs(cnt - 1))
      return true;
    row[x] += 1 << t;
    col[y] += 1 << t;
    cell[x / 3][y / 3] += 1 << t;
    s[x][y] = '.';
  }
  return false;
}
int main() { 
   
  for (int i = 0; i < N; i++)
    map[1 << i] = i;
  for (int i = 0; i < (1 << N); i++) { 
   
    int k = 0;
    for (int j = i; j; j -= lowbit(j)) { 
   
      k++;
    }
    ones[i] = k;
  }
  while (true) { 
   
    for (int i = 0; i < N; i++)
      cin >> s[i];
    init();
    cnt = 0;
    for (int i = 0; i < 9; i++) { 
   
      for (int j = 0; j < 9; j++) { 
   
        if (s[i][j] != '.') { 
   
          int t = s[i][j] - '1';
          row[i] -= 1 << t;
          col[j] -= 1 << t;
          cell[i / 3][j / 3] -= 1 << t;
        } else { 
   
          cnt++;
        }
      }
    }
    dfs(cnt);
    for (int i = 0; i < N; i++) { 
   
      for (int j = 0; j < N; j++) { 
   
        cout << s[i][j] << ' ';
      }
      cout << endl;
    }
  }
  return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/200817.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • CICD构建实验「建议收藏」

    CICD构建实验「建议收藏」CICDCICD是一个可以集部署、拉取、上传等于一体的架构环境,它支持一线进行部署,免去了人工一条条的进行部署环境的工作流程,大大降低了人力手工运维成本和出错率。CICD的搭建需要至少三台服务器,他们分别监管着Harbor(镜像仓库存储),git(开发代码仓库存储),Jenkings(一键化部署)企业级镜像Harbor部署docker镜像级的存储可以储存在dockerhub上,也可以储存在自建本地仓库上,而Harbor属于本地仓库的其中一种,该软件可以提供图形化界面操作,安装简单,且方便查看。

    2022年5月5日
  • 男生说fb是什么梗_男生聊污是什么意思 男生会对谁聊污

    男生说fb是什么梗_男生聊污是什么意思 男生会对谁聊污男生聊污是在暗示么,肯定啊,经常聊肯定是想要发生些什么,如果能够得到回应肯定就进一步发展了。还有一种情况是为了口嗨,不管是真正的性、还是聊天是聊污,都是为了嗨,最终的目的还是为了上床。一般来讲,女生是不喜欢这样的话题,甚至讲得过份的话会觉得受到侮辱。男生一般不会随便的在女生面前讲起这些话题,讲起来肯定是有目的。费玉清其实也是一种试探,如果两个人能够聊下去,哪怕不发展到床上这种地步,但是也会聊的非常…

    2022年7月25日
  • mysql 唯一索引_mysql主键和唯一索引的区别

    mysql 唯一索引_mysql主键和唯一索引的区别Mysql索引大概有五种类型:普通索引(INDEX):最基本的索引,没有任何限制唯一索引(UNIQUE):与”普通索引”类似,不同的就是:索引列的值必须唯一,但允许有空值。主键索引(PRIMARY):它是一种特殊的唯一索引,不允许有空值。全文索引(FULLTEXT):可用于MyISAM表,mysql5.6之后也可用于innodb表,用于在一篇文章中,检索文本信息的,针对较大的数据,生成全文索引很耗时和空间。联合(组合)索引:为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原

    2022年9月20日
  • 记录Depix工具的使用

    记录Depix工具的使用这个月初有一个挺让人振奋的消息,说是出了一款开源去“马赛克“工具,三天就收获了3k+star,现在star数已经达到了13.7k了,项目地址:https://github.com/beurtschipper/Depix。我是没有这种世俗的欲望的,所以当时就没关注,直到昨天”纵横杯”网络安全竞赛Misc中专门出了一个马赛克的题,就给出了下面这张图片师傅们调侃说近视眼摘下眼镜离远一点就能看清楚了,我试了一下只能看出轮廓,但是还是看不清,这就需要用到Depix这个神奇的工具了。我这里是在windows系

    2022年6月29日
  • spring-schedul实现动态添加定时任务

    spring-schedul实现动态添加定时任务

    2021年7月12日
  • 华硕 X201E 拆机

    华硕 X201E 拆机每次笔记本拆机,装好之后,就会发现多了几个螺丝,忘了从哪拧下来了下面记录下华硕X201E清灰拆机过程

    2022年6月27日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号