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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289122.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

工业互联网上市公司.NET开发岗位来袭!!!

01公司简介2022 ABOUT /公司简介安徽容知日新科技股份有限公司&#xff08;股票代码&#xff1a;688768&#xff09;于2007年在合肥市成立&#xff0c;是一家工业互联网领域的高新技术企业&#xff0c;为客户提供设备智能运维平台解决方案和动设备预测性维护产品及服务。容知日…

mysql数据库密码为空_注意MySQL数据库用户root密码为空

注意MySQL数据库用户root密码为空文章作者&#xff1a;网友投稿 发布时间&#xff1a;2008-08-14 19:11:51 来源&#xff1a;网络看到这大家肯定知道了&#xff0c;就是利用mysql输出一个可执行的文件而已。为什么不用bat呢&#xff0c;因为启动运行时会有明显的dos窗口出来&…

【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记24 popovers弹窗

上几话中我们详细了解了几种segue&#xff0c;我们也了解到了多MVC模式的几种控制器&#xff0c;比如导航、选项卡和分栏&#xff0c;除了这三种多MVC的模式之外&#xff0c;还有一种popover&#xff0c;它跟其他三种不太一样。首先先来认识一下popover&#xff08;弹窗&#x…

shell 脚本加密

想想好久没更新博客了&#xff0c;今天在群里看到讨论关于shell脚本加密的事情。想想也是&#xff0c;我们在写脚本有时候会配置相关账号和密码的事情&#xff0c;这样只要能权限都能看到该信息&#xff0c;非常的不安全&#xff0c;有没有在正常运行的情况下对文件进行加密。大…

React Native之didFocus和didBlur

1 didFocus和didBlur解释 didFocus - the screen focused (if there was a transition, the transition completed)didBlur - the screen unfocused (if there was a transition, the transition completed) didFocus是指当前页面第一次加载的时候会调用一次 didBlur是指当前…

python语法详解_解析 Python3 基础语法

行与缩进 python最具特色的就是使用缩进来表示代码块&#xff0c;不需要使用大括号 {} 。 缩进的空格数是可变的&#xff0c;但是同一个代码块的语句必须包含相同的缩进空格数。实例如下&#xff1a; if True: print ("True") else: print ("False") Color…

ENVI扩展工具:利用波段运算修改NaN方法总结

NaN为Not a Number的缩写,在遥感图像中属于异常值。很多用户有修改NaN的需求,比如把0值修改为NaN,或把NaN修改为0值等。由于波段运算公式较为复杂,现归纳如下。 1. 直接利用波段运算进行 Ÿ 修改0值为NaN – float(b1)*b1/b1 Ÿ 修改特定值(250)为Na…

ASP.NET 6 中间件 - 介绍与基础

这是一个关于 .NET 6 中间件的系列文章。在这个系列中&#xff0c;我们将了解到什么是中间件&#xff0c;它能够做什么&#xff0c;以及我们为什么要使用它&#xff0c;并演示几种不同类型的中间件的实现。之后&#xff0c;我们会进一步了解中间件所在的管道&#xff0c;以及如…

数组的迭代数组里面每个对象添加属性值_JS数组和对象循环遍历的几种实现方式...

数组遍历1. 普通for循环let arr [1,2,3,4,5] for (let i 0; i < arr.length; i) {console.log(arr[i]) } // 输出结果 // 1 // 2 // 3 // 4 // 52. 优化普通for循环let arr [1,2,3,4,5] for(var j 0,len arr.length; j < len; j){console.log(arr[j]); }3. forEach循…

Blend4精选案例图解教程(三):一键拖拽

原文:Blend4精选案例图解教程&#xff08;三&#xff09;&#xff1a;一键拖拽拖拽效果&#xff0c;常规实现方法是定义MoveLeftDwon、MoveLeftUp、MouseMove事件&#xff0c;在Blend的世界里&#xff0c;实现对象的拖拽&#xff0c;可以不写一行代码&#xff0c;而且非常简单&…

redis学习之三配置文件redis.conf 的含义

摘自http://www.runoob.com/redis/redis-conf.html 安装redis之后的第一件事&#xff0c;我就开始配置密码&#xff0c;结果总是不生效&#xff0c;而我居然还没想到原因。今天突然用命令行设置了密码&#xff0c;居然可以了。然后info一下&#xff0c;看到配置文件位置才恍然大…

React Native之hardwareBackPress

1 hardwareBackPress 我们用hardwareBackPress来监听手机物理返回键 2 js那边常用写法 BackHandler.addEventListener(hardwareBackPress, this._back); 3 我们看下Android源代码分析是怎么触发到这里来的 1) ReactActivity.java里面的部分代码如下 Overridepublic void o…

python画气泡图_​用Python把图做的好看点:用Matplotlib画个好看的气泡图

我们继续来把简单的图形丢到极坐标&#xff0c;这次是气泡图和柱状图&#xff0c;临摹的对象是澎湃美数课这个图看起来很好看&#xff0c;原理其实很简单&#xff0c;把柱状图和气泡图从笛卡尔坐标系中转移到极坐标系中来就OK 我们开始本次的临摹吧 本期的主题如下&#xff1a;…

C#输入框InputBox问题

C#里面没有像VB一样的InputBox,但是像InputBox一样的控件在程序中很实用,这里有两种方法实现: 一、调用VB里的InputBox 首先添加引用Microsoft.VisualBasic,然后在命名空间中引用(using Microsoft.VisualBasic;)。 举个实例: using System; using System.Collections.Ge…

mysql为什么添加索引_当我添加新索引时,为什么MySQL中索引的基数保持不变?

如果表中只有1行,则索引的基数当然应为1.它只是计算唯一值的数量.如果您将索引视为基于存储桶的查找表(如散列),则基数是存储桶的数量.以下是它的工作原理&#xff1a;当您在一组列(a,b,c,d)上构建索引时,数据库将遍历表中的所有行,查看每行的4个列的有序四元组.假设你的表看起…

win32 注册表操作

创建键 RegCreateKeyEx int SetRecordVideoSavedDays(int newSavedDays)2 {3 HKEY hSubKey NULL;4 LONG lRet 0;5 DWORD dwType 0;6 int iRet 0;7 8 do 9 {10 if (newSavedDays < 0)11 {12 printf(&quo…

进程间通信(一)

1 消息队列 消息队列是消息的链接表 , 存放在内核中并由消息队列标识符标识。 m s g g e t用于创建一个新队列或打开一个现存的队列。 m s g s n d用于将新消息添加到队列尾端。 m s g r c v用于从队列中取消息。 调用的第一个函数通常是m s g g e t&#xff0c;其功能是打开一…

Asp.NET Core一个接口的多个实现如何基于当前HTTP请求注册

前言假设我们有三个Service类实现了同一接口&#xff0c;示例代码如下&#xff1a;public interface IService { } public class ServiceA : IService { } public class ServiceB : IService { } public class ServiceC : IService { }我们希望在运行时使用依赖注入指定其具体…

Loadrunner 接口测试方法

其实无论用那种测试方法&#xff0c;接口测试的原理是通过测试程序模拟客户端向服务器发送请求报文&#xff0c;服务器接收请求报文后对相应的报文做出处理然后再把应答报文发送给客户端&#xff0c;客户端接收应答报文这一个过程。一、基于通用http/html请求大家都知道LoadRun…

React Native之react-native bundle --platform android --dev false --entry-file index.js --bundle失败

1 问题 react native项目在assert目录下面生成index.android.bundle文件用下面的命令 react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/r…