搜索实现:解决数独有两种思考策略,一种是枚举当前格能填的数字的种数,这里有一优化策略就是先搜索能填入种数小的格子;另一种是考虑处理某一行(列、宫)时,对于某一个没用过的数字,若该行(列、宫)只有一个可行的空白格时,就只能将该数字填入此格中。第二种实现起来略麻烦,此处仅实现第一种策略,并调整搜索顺序进行优化操作,优先搜索能填数字种数较小的格子。

另外,在搜索时,条件判断的效率尤为重要,故分别记录各行、各列、各宫已经出现的数字,这样就可以直接判断该空格填入某数字是否可行。

以POJ2676为例,无调整搜索顺序的优化,用时26ms,调整搜索顺序后用时0ms。

 1 //dfs搜索,枚举当前格能填的数字
 2 #include <stdio.h>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 9;
 6 char mp[N+1][N+1];
 7 int row[N+1], col[N+1], squ[N+1];
 8 struct p{
 9     int x, y, z;
10     p(int a = 0, int b = 0, int c = 0) :x(a), y(b), z(c){}
11     bool operator <(const p& m)const {
12         return z < m.z;
13     }
14 };
15 p pa[N*N+1];
16 int tot;
17
18 bool dfs(int d) {
19     if (d == tot) return true;
20
21     for(int i = d; i < tot; i++){
22         int nn = 0, x = pa[i].x, y = pa[i].y;
23         pa[i].z = 0;
24         for(int j = 1; j < 512; j <<= 1)
25             if( !(row[x]&j) && !(col[y]&j) && !(squ[x/3*3+y/3]&j) )
26                 pa[i].z++;
27     }
28     sort(pa+d, pa+tot);//调整搜素顺序!!
29
30     int x = pa[d].x, y = pa[d].y;
31     for(int i = 1; i <= N; i++){
32         int j = 1 <<(i-1);
33         if(!(row[x]&j) && !(col[y]&j) && !(squ[x/3*3+y/3]&j)){
34             row[x] ^= j, col[y] ^= j, squ[x/3*3+y/3] ^= j;
35             mp[x][y] = '0'+i;
36             if(dfs(d+1)) return true;
37             row[x] ^= j, col[y] ^= j, squ[x/3*3+y/3] ^= j;
38         }
39     }
40     return false;
41 }
42
43 int main(){
44     int t; scanf("%d", &t);
45     while(t--){
46         for(int i = 0; i < 9; i++)
47             for(int j = 0; j < 9; j++)
48                 scanf(" %c", &mp[i][j]);
49
50         for(int i = 0; i < N; i++)
51             row[i] = col[i] = squ[i] = 0;
52         tot = 0;
53
54         for(int i = 0; i < N; i++)
55             for(int j = 0; j < N; j++)
56                 if(mp[i][j] != '0'){
57                     int idx = mp[i][j]-'1';
58                     row[i] |= 1<<idx, col[j] |= 1<<idx, squ[i/3*3+j/3] |= 1<<idx;
59                 }
60                 else
61                     pa[tot++] = p(i, j);
62
63         for(int i = 0; i < tot; i++){
64             int nn = 0, x = pa[i].x, y = pa[i].y;
65             for(int j = 1; j < 512; j <<= 1)
66                 if( !(row[x]&j) && !(col[y]&j) && !(squ[x/3*3+y/3]&j) )
67                     pa[i].z++;
68         }
69
70         dfs(0);
71
72         for (int i = 0; i < 9; ++i)
73             puts(mp[i]);
74     }
75     return 0;
76 }

View Code

DLX算法的POJ2676

  1 //******************************************************//
  2 //输入T表示T组数据。                                    //
  3 //每组数据为9个长度为9的字符串,空白处以字符0替代。        //
  4 //POJ2676                                               //
  5 //******************************************************//
  6
  7 #include <bits/stdc++.h>
  8 using namespace std;
  9 const int maxnode = 100010;
 10 const int MaxM = 1010;
 11 const int MaxN = 1010;
 12 struct DLX{
 13     int n, m, size;                 //行数,列数,总数
 14     int U[maxnode], D[maxnode], R[maxnode], L[maxnode], Row[maxnode], Col[maxnode];
 15     int H[MaxN], S[MaxM];           //S记录该列剩余1的个数,H表示该行最左端的1
 16     int ansd, ans[MaxN];
 17
 18     void init(int _n, int _m){
 19         n = _n;
 20         m = _m;
 21         for(int i = 0; i <= m; i++){
 22             S[i] = 0;
 23             U[i] = D[i] = i;
 24             L[i] = i-1;
 25             R[i] = i+1;
 26         }
 27         R[m] = 0; L[0] = m;
 28         size = m;
 29         memset(H, -1, sizeof(H));
 30     }
 31     void Link(int r, int c){
 32         size++;
 33         Col[size] = c, Row[size] = r;
 34         S[c]++;
 35         U[size] = U[c], D[size] = c;
 36         D[U[c]] = size;
 37         U[c] = size;
 38         if (H[r] != -1) {
 39             R[size] = H[r] ;
 40             L[size] = L[H[r]] ;
 41             R[L[size]] = size ;
 42             L[R[size]] = size ;
 43         }
 44         else
 45             H[r] = L[size] = R[size] = size ;
 46     }
 47     void remove(int c){//覆盖第c列。删除第c列及能覆盖到该列的行,防止重叠
 48         L[R[c]] = L[c]; R[L[c]] = R[c];
 49         for(int i = D[c]; i != c; i = D[i])
 50             for(int j = R[i]; j != i; j = R[j]){
 51                 U[D[j]] = U[j];
 52                 D[U[j]] = D[j];
 53                 --S[Col[j]];
 54             }
 55     }
 56     void resume(int c){
 57         for(int i = U[c]; i != c; i = U[i])
 58             for(int j = L[i]; j != i; j = L[j]){
 59                 ++ S[Col[j]];
 60                 U[D[j]] = j;
 61                 D[U[j]] = j;
 62             }
 63         L[R[c]] = R[L[c]] = c;
 64     }
 65     //d为递归深度
 66     bool dance(int d){
 67         if(R[0] == 0){
 68             ansd = d;
 69             return true;
 70         }
 71         int c = R[0];
 72         for(int i = R[0]; i != 0; i = R[i])
 73             if(S[i] < S[c])
 74                 c = i;
 75         remove(c);
 76         for(int i = D[c];i != c;i = D[i]){
 77             ans[d] = Row[i];
 78             for(int j = R[i]; j != i; j = R[j]) remove(Col[j]);
 79             if(dance(d+1)) return true;
 80             for(int j = L[i]; j != i; j = L[j]) resume(Col[j]);
 81         }
 82         resume(c);
 83         return false;
 84     }
 85 };
 86 DLX g;
 87 char s[15][15];
 88 int main(){
 89     int t;
 90     scanf("%d", &t);
 91     while(t--){
 92         for(int i = 0; i < 9; i++)
 93             scanf("%s", s[i]);
 94
 95         g.init(81*9, 81+81+81+81);
 96
 97         for(int i = 0; i < 9; i++)
 98             for(int j = 0; j < 9; j++){
 99                 int x = i, y = j, z = x/3*3+y/3, w = i*9+j;
100                 if(s[i][j] == '0'){
101                     for(int k = 1; k <= 9; k++){
102                         g.Link(w*9+k, w+1);
103                         g.Link(w*9+k, 81+x*9+k);
104                         g.Link(w*9+k, 162+y*9+k);
105                         g.Link(w*9+k, 243+z*9+k);
106                     }
107                 }
108                 else {
109                     int t = s[i][j]-'0';
110                     g.Link(w*9+t, w+1);
111                     g.Link(w*9+t, 81+x*9+t);
112                     g.Link(w*9+t, 162+y*9+t);
113                     g.Link(w*9+t, 243+z*9+t);
114                 }
115             }
116         g.dance(0);
117
118         for(int i = 0; i < g.ansd; i++){
119             int t = g.ans[i];
120             int a = (t-1)/9, b = (t-1)%9+'1';
121             s[a/9][a%9] = b;
122         }
123         for(int i = 0; i < 9; i++)
124             puts(s[i]);
125     }
126     return 0;
127 }

View Code

DLX算法很容易,套个框架就能解决了,还能高效解决变形数独。用HDU4069,一个变形数独为例。

  1 //******************************************************//
  2 //hdu4069                                               //
  3 //******************************************************//
  4 #include <bits/stdc++.h>
  5 using namespace std;
  6 const int MaxM = 1000+10;
  7 const int MaxN = 1000+10;
  8 const int maxnode = MaxM*MaxN;
  9 struct DLX{
 10     int n, m, size;                 //行数,列数,总数
 11     int U[maxnode], D[maxnode], R[maxnode], L[maxnode], Row[maxnode], Col[maxnode];
 12     int H[MaxN], S[MaxM];           //S记录该列剩余1的个数,H表示该行最左端的1
 13     int ansd, ans[MaxN];
 14     int temp[MaxN];
 15     int tot;
 16
 17     void init(int _n, int _m){
 18         n = _n;
 19         m = _m;
 20         for(int i = 0; i <= m; i++){
 21             S[i] = 0;
 22             U[i] = D[i] = i;
 23             L[i] = i-1;
 24             R[i] = i+1;
 25         }
 26         R[m] = 0; L[0] = m;
 27         size = m;
 28         memset(H, -1, sizeof(H));
 29
 30         tot = 0;
 31     }
 32     void Link(int r, int c){
 33         size++;
 34         Col[size] = c, Row[size] = r;
 35         S[c]++;
 36         U[size] = U[c], D[size] = c;
 37         D[U[c]] = size;
 38         U[c] = size;
 39         if (H[r] != -1) {
 40             R[size] = H[r] ;
 41             L[size] = L[H[r]] ;
 42             R[L[size]] = size ;
 43             L[R[size]] = size ;
 44         }
 45         else
 46             H[r] = L[size] = R[size] = size ;
 47     }
 48     void remove(int c){//覆盖第c列。删除第c列及能覆盖到该列的行,防止重叠
 49         L[R[c]] = L[c]; R[L[c]] = R[c];
 50         for(int i = D[c]; i != c; i = D[i])
 51             for(int j = R[i]; j != i; j = R[j]){
 52                 U[D[j]] = U[j];
 53                 D[U[j]] = D[j];
 54                 --S[Col[j]];
 55             }
 56     }
 57     void resume(int c){
 58         for(int i = U[c]; i != c; i = U[i])
 59             for(int j = L[i]; j != i; j = L[j]){
 60                 ++ S[Col[j]];
 61                 U[D[j]] = j;
 62                 D[U[j]] = j;
 63             }
 64         L[R[c]] = R[L[c]] = c;
 65     }
 66     //d为递归深度
 67     int dance(int d){
 68         if(R[0] == 0){
 69             ansd = d;
 70             for(int i = 0; i < ansd; i++)
 71                 ans[i] = temp[i];
 72             tot++;
 73             return tot;
 74         }
 75         int c = R[0];
 76         for(int i = R[0]; i != 0; i = R[i])
 77             if(S[i] < S[c])
 78                 c = i;
 79         remove(c);
 80         for(int i = D[c];i != c;i = D[i]){
 81             temp[d] = Row[i];
 82             for(int j = R[i]; j != i; j = R[j]) remove(Col[j]);
 83             if(dance(d+1) > 1) return tot;
 84             for(int j = L[i]; j != i; j = L[j]) resume(Col[j]);
 85         }
 86         resume(c);
 87         return tot;
 88     }
 89 };
 90 DLX g;
 91
 92 int a[10][10];
 93 int gird[10][10];
 94 int d[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};//u,r,d,l
 95 void dfs(int x, int y, int color){
 96     gird[x][y] = color;
 97     for(int i = 0; i < 4; i++){
 98         int xx = x+d[i][0], yy = y+d[i][1];
 99         if((a[x][y] & (16<<i))== 0&&xx >= 0&& xx < 9&&yy >= 0&&yy <9&&gird[xx][yy] == -1)
100             dfs(xx, yy, color);
101     }
102     return ;
103 }
104
105 int main(){
106     int T; scanf("%d", &T);
107     for(int ca = 1; ca <= T; ca++){
108         for(int i = 0; i < 9; i++)
109             for(int j = 0; j < 9; j++)
110                 scanf("%d", &a[i][j]);
111         memset(gird, -1, sizeof(gird));
112         int tt = 0;
113         for(int i = 0; i < 9; i++)
114             for(int j = 0; j < 9; j++)
115                 if(gird[i][j] == -1) dfs(i, j, tt++);
116
117         g.init(81*9, 81*4);
118         for(int i = 0; i < 9; i++)
119             for(int j = 0; j < 9; j++){
120                 int t = (a[i][j]&15), w = i*9+j, x = i, y = j, z = gird[i][j];
121                 if(t){
122                     g.Link(w*9+t, w+1);
123                     g.Link(w*9+t, 81+x*9+t);
124                     g.Link(w*9+t, 162+y*9+t);
125                     g.Link(w*9+t, 243+z*9+t);
126                 }else {
127                     for(int k = 1; k <= 9; k++){
128                         g.Link(w*9+k, w+1);
129                         g.Link(w*9+k, 81+x*9+k);
130                         g.Link(w*9+k, 162+y*9+k);
131                         g.Link(w*9+k, 243+z*9+k);
132                     }
133                 }
134             }
135
136         printf("Case %d:\n", ca);
137         int ret = g.dance(0);
138         if(ret == 1){
139             for(int i = 0; i < g.ansd; i++){
140                 int t = g.ans[i];
141                 int x = (t-1)/9, y = (t-1)%9+1;
142                 a[x/9][x%9] = y;
143             }
144             for(int i = 0; i < 9; i++){
145                 for(int j = 0; j < 9; j++)
146                     printf("%d", a[i][j]);
147                 puts("");
148             }
149         }
150         else if(ret > 1) puts("Multiple Solutions");
151         else puts("No solution");
152     }
153     return 0;
154 }

View Code

转载于:https://www.cnblogs.com/dirge/p/5206730.html

POJ2676,HDU4069解决数独的两种实现:DFS、DLX相关推荐

  1. 翻硬币—两种方法 dfs 贪心

    来源:第四届蓝桥杯省赛C++B组 翻硬币 小明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情 ...

  2. 哈希表解决冲突的两种方式

    虽然我们不希望发生冲突,但实际上发生冲突的可能性仍是存在的.当关键字值域远大于哈希表的长度,而且事先并不知道关键字的具体取值时.冲突就难免会发 生.另外,当关键字的实际取值大于哈希表的长度时,而且表中 ...

  3. idea双击无反应,打不开的解决方法,两种情况。

    idea今天突然打不开了,双击右键都没反应, 任务管理器里也没有进程. 下面是解决过程.还有一些坑. 首先第一种情况就是第一次就打不开的,我之前打开过,但是因为网上大多都是这种解决方法就先试试. 首先 ...

  4. 字符串缓冲区太小怎么解决_epoll的两种模式 ET和LT printf的缓冲区问题 边缘非阻塞模式...

    学习于:https://www.bilibili.com/video/av44660437/?p=9 前文:何柄融:多路复用I/O select poll epoll 何柄融:select poll ...

  5. VMware下centos/Linux鼠标移动闪烁解决办法(两种办法100%解决)

    1. Windows10设置--设备--鼠标--其他鼠标选项--指针选项--(勾选)显示指针轨迹(D)--(将进度条调至短) 打开"Windows设置",点击"设备&qu ...

  6. android中view手势滑动冲突的两种解决方法

    android中view手势滑动冲突的解决方法,主要解决方法有两种,外部和内部拦截.有需要的可以参考下. Android手势事件的冲突跟点击事件的分发过程息息相关,由三个重要的方法来共同完成,分别是: ...

  7. PDF的两种密码忘记了,怎么解决

    PDF文件带有两种加密方式,大家一定都很熟悉,因为大部分文件都有这两种加密方式,比如Word.Excel.PPT.压缩包等.PDF文件也有这两种密码. 那就是:打开密码.编辑限制 打开密码:就是在我们 ...

  8. 解决GitHub下载资源慢的问题(两种方法)

    解决GitHub下载资源慢的问题    最近需要使用GitHub下载一个比较大的资源,在以前一直用GitHub下载开源资源,速度一直都是很慢的,但是由于这次文件比较大,使用GitHub进行下载,速度只 ...

  9. java解压缩文件名乱码_解决JDKZipEntry压缩文件名乱码的两种方法

    当我们在创建java的项目过程中,有时候会遇到一些棘手的问题,就比如说:在JDk zipEntry压缩中文文件名出现乱码的问题.那么对于这个问题,我们应该怎样来解决呢?今天我们就一起来学习一下它的解决 ...

最新文章

  1. PyCharm有些库(函数)没有代码提示
  2. java链表寻找中间节点
  3. c语言给定变量a的初始值,2018年9月计算机二级C语言考试冲刺提分试题(一)
  4. 【Git 】命令总结记录
  5. bank holiday in uk 2020
  6. 温州大学《机器学习》课程课件(七、决策树)
  7. java 类无法实例_Java无法从类实例访问类方法
  8. 大数据分析 es hive_使用Hive和iReport进行大数据分析
  9. termux配置python安装kali_安卓安装kali linux之Termux
  10. 4-1 简单输出整数 (10分)
  11. jmeter 能调用python吗_jmeter 执行python脚本的方法 。(亲测ok)
  12. 虚拟机安装Ubuntu解决自带Firefox浏览器不能看视频,提示无Flash插件问题!安装flash!
  13. JS-记事本(代码)
  14. 行为主义心理学在游戏领域的10年发展
  15. mysql5.0基础语句_mysql基础语句
  16. Excel批量生成条形码
  17. 故障:恢复 Windows 默认共享
  18. Java基础-面向对象-封装继承多态
  19. php 定义宏函数,汇编语言宏函数
  20. 举个栗子~Minitab 技巧(5):掌握常用快捷键,提高统计分析效率

热门文章

  1. Java中 a+=b和a=a+b有什么区别?
  2. linux的less命令如何退出,Linux命令详解之less命令
  3. 不懂开发的人员,请不要随意说这功能很容易实现
  4. Linux文本截取命令cut​笔记
  5. .NET开发中应该遵循的几点建议
  6. 社交中的黄金法则,你要细细体会品味
  7. 华为的鸿蒙系统是海思_死心了!华为鸿蒙系统首款终端确认,不是手机
  8. html在线拖拽环绕,jQuery实现html元素拖拽
  9. 从 vue-cli 源码中,我发现了27行读取 json 文件有趣的 npm 包
  10. Cocopods的升级错误解决