POJ2676,HDU4069解决数独的两种实现:DFS、DLX
搜索实现:解决数独有两种思考策略,一种是枚举当前格能填的数字的种数,这里有一优化策略就是先搜索能填入种数小的格子;另一种是考虑处理某一行(列、宫)时,对于某一个没用过的数字,若该行(列、宫)只有一个可行的空白格时,就只能将该数字填入此格中。第二种实现起来略麻烦,此处仅实现第一种策略,并调整搜索顺序进行优化操作,优先搜索能填数字种数较小的格子。
另外,在搜索时,条件判断的效率尤为重要,故分别记录各行、各列、各宫已经出现的数字,这样就可以直接判断该空格填入某数字是否可行。
以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相关推荐
- 翻硬币—两种方法 dfs 贪心
来源:第四届蓝桥杯省赛C++B组 翻硬币 小明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情 ...
- 哈希表解决冲突的两种方式
虽然我们不希望发生冲突,但实际上发生冲突的可能性仍是存在的.当关键字值域远大于哈希表的长度,而且事先并不知道关键字的具体取值时.冲突就难免会发 生.另外,当关键字的实际取值大于哈希表的长度时,而且表中 ...
- idea双击无反应,打不开的解决方法,两种情况。
idea今天突然打不开了,双击右键都没反应, 任务管理器里也没有进程. 下面是解决过程.还有一些坑. 首先第一种情况就是第一次就打不开的,我之前打开过,但是因为网上大多都是这种解决方法就先试试. 首先 ...
- 字符串缓冲区太小怎么解决_epoll的两种模式 ET和LT printf的缓冲区问题 边缘非阻塞模式...
学习于:https://www.bilibili.com/video/av44660437/?p=9 前文:何柄融:多路复用I/O select poll epoll 何柄融:select poll ...
- VMware下centos/Linux鼠标移动闪烁解决办法(两种办法100%解决)
1. Windows10设置--设备--鼠标--其他鼠标选项--指针选项--(勾选)显示指针轨迹(D)--(将进度条调至短) 打开"Windows设置",点击"设备&qu ...
- android中view手势滑动冲突的两种解决方法
android中view手势滑动冲突的解决方法,主要解决方法有两种,外部和内部拦截.有需要的可以参考下. Android手势事件的冲突跟点击事件的分发过程息息相关,由三个重要的方法来共同完成,分别是: ...
- PDF的两种密码忘记了,怎么解决
PDF文件带有两种加密方式,大家一定都很熟悉,因为大部分文件都有这两种加密方式,比如Word.Excel.PPT.压缩包等.PDF文件也有这两种密码. 那就是:打开密码.编辑限制 打开密码:就是在我们 ...
- 解决GitHub下载资源慢的问题(两种方法)
解决GitHub下载资源慢的问题 最近需要使用GitHub下载一个比较大的资源,在以前一直用GitHub下载开源资源,速度一直都是很慢的,但是由于这次文件比较大,使用GitHub进行下载,速度只 ...
- java解压缩文件名乱码_解决JDKZipEntry压缩文件名乱码的两种方法
当我们在创建java的项目过程中,有时候会遇到一些棘手的问题,就比如说:在JDk zipEntry压缩中文文件名出现乱码的问题.那么对于这个问题,我们应该怎样来解决呢?今天我们就一起来学习一下它的解决 ...
最新文章
- PyCharm有些库(函数)没有代码提示
- java链表寻找中间节点
- c语言给定变量a的初始值,2018年9月计算机二级C语言考试冲刺提分试题(一)
- 【Git 】命令总结记录
- bank holiday in uk 2020
- 温州大学《机器学习》课程课件(七、决策树)
- java 类无法实例_Java无法从类实例访问类方法
- 大数据分析 es hive_使用Hive和iReport进行大数据分析
- termux配置python安装kali_安卓安装kali linux之Termux
- 4-1 简单输出整数 (10分)
- jmeter 能调用python吗_jmeter 执行python脚本的方法 。(亲测ok)
- 虚拟机安装Ubuntu解决自带Firefox浏览器不能看视频,提示无Flash插件问题!安装flash!
- JS-记事本(代码)
- 行为主义心理学在游戏领域的10年发展
- mysql5.0基础语句_mysql基础语句
- Excel批量生成条形码
- 故障:恢复 Windows 默认共享
- Java基础-面向对象-封装继承多态
- php 定义宏函数,汇编语言宏函数
- 举个栗子~Minitab 技巧(5):掌握常用快捷键,提高统计分析效率
热门文章
- Java中 a+=b和a=a+b有什么区别?
- linux的less命令如何退出,Linux命令详解之less命令
- 不懂开发的人员,请不要随意说这功能很容易实现
- Linux文本截取命令cut​笔记
- .NET开发中应该遵循的几点建议
- 社交中的黄金法则,你要细细体会品味
- 华为的鸿蒙系统是海思_死心了!华为鸿蒙系统首款终端确认,不是手机
- html在线拖拽环绕,jQuery实现html元素拖拽
- 从 vue-cli 源码中,我发现了27行读取 json 文件有趣的 npm 包
- Cocopods的升级错误解决