POJ3076 Sudoku 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目(传送门)
题意概括
给出一个残缺的16*16数独,求解。
题解
学完这个之后,再思考这一题。同样,每个位置每种取值4个信息。
数独共256个格子,每个格子都得填一个数,那么,我们要精确覆盖每一个格子,所以我们首先建立1~256列。
然后还有16行,每行1~16,每行都得精确覆盖,16行,又得建立16*16=256列;
然后还有16列,每列1~16,同理。
然后还有16个4*4的小格子,每个里面1~16,也同理。
那么总共要建立4*256=1024列。
代码
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=,M=,S=N*+M;
struct DLX{
int n,m,cnt;
int x[S],y[S],L[S],R[S],U[S],D[S];
int C[M],anscnt,ans[N];
void init(int c){
memset(x,,sizeof x),memset(y,,sizeof y);
memset(L,,sizeof L),memset(R,,sizeof R);
memset(U,,sizeof U),memset(D,,sizeof D);
memset(C,,sizeof C),memset(ans,,sizeof ans);
anscnt=,m=c;
for (int i=;i<=m;i++)
L[i]=i-,R[i]=i+,U[i]=D[i]=i;
L[]=m,R[m]=,cnt=m;
}
void link(int i,int j){
cnt++;
x[cnt]=i;
y[cnt]=j;
L[cnt]=cnt-;
R[cnt]=cnt+;
D[cnt]=j;
D[U[j]]=cnt;
U[cnt]=U[j];
U[j]=cnt;
C[j]++;
}
void Delete(int k){
L[R[k]]=L[k];
R[L[k]]=R[k];
for (int i=D[k];i!=k;i=D[i])
for (int j=R[i];j!=i;j=R[j]){
U[D[j]]=U[j];
D[U[j]]=D[j];
C[y[j]]--;
}
}
void Reset(int k){
L[R[k]]=k;
R[L[k]]=k;
for (int i=U[k];i!=k;i=U[i])
for (int j=L[i];j!=i;j=L[j]){
U[D[j]]=j;
D[U[j]]=j;
C[y[j]]++;
}
}
bool solve(){
if (R[]==)
return true;
anscnt++;
int k=R[];
for (int i=R[k];i!=;i=R[i])
if (C[i]<C[k])
k=i;
Delete(k);
for (int i=D[k];i!=k;i=D[i]){
ans[anscnt]=x[i];
for (int j=R[i];j!=i;j=R[j])
Delete(y[j]);
if (solve())
return true;
for (int j=L[i];j!=i;j=L[j])
Reset(y[j]);
}
Reset(k);
anscnt--;
return false;
}
}dlx;
int a[][],x[N],y[N],z[N];
char s[];
int hash(int a,int b,int c){
return a*+b*+c+;
}
int main(){
while (~scanf("%s",s+)){
for (int i=;i<=;i++){
for (int j=;j<=;j++)
if (s[j]=='-')
a[i][j]=;
else
a[i][j]=s[j]-'A'+;
if (i<)
scanf("%s",s+);
}
dlx.init();
int Row=;
for (int i=;i<=;i++)
for (int j=;j<=;j++){
int st,en;
if (a[i][j]==)
st=,en=;
else
st=en=a[i][j];
for (int k=st;k<=en;k++){
Row++;
x[Row]=i,y[Row]=j,z[Row]=k;
int first=dlx.cnt+;
dlx.link(Row,hash(,i-,j-));
dlx.link(Row,hash(,i-,k-));
dlx.link(Row,hash(,j-,k-));
dlx.link(Row,hash(,((i-)/)*+(j-)/,k-));
dlx.L[first]=dlx.cnt;
dlx.R[dlx.cnt]=first;
}
}
bool found=dlx.solve();
for (int i=;i<=dlx.anscnt;i++)
a[x[dlx.ans[i]]][y[dlx.ans[i]]]=z[dlx.ans[i]];
for (int i=;i<=;puts(""),i++)
for (int j=;j<=;j++)
printf("%c",a[i][j]+'A'-);
puts("");
}
return ;
}
POJ3076 Sudoku 舞蹈链 DLX的更多相关文章
- POJ3074 Sudoku 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求解. 题解 DLX + 矩阵构建 (两个传送门) 代码 #include & ...
- POJ2676 Sudoku 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求解.SPJ 题解 DLX + 矩阵构建 (两个传送门) 代码 #includ ...
- 舞蹈链 DLX
欢迎访问——该文出处-博客园-zhouzhendong 去博客园看该文章--传送门 舞蹈链是一个非常玄学的东西…… 问题模型 精确覆盖问题:在一个01矩阵中,是否可以选出一些行的集合,使得在这些行的集 ...
- [学习笔记] 舞蹈链(DLX)入门
"在一个全集\(X\)中若干子集的集合为\(S\),精确覆盖(\(\boldsymbol{Exact~Cover}\))是指,\(S\)的子集\(S*\),满足\(X\)中的每一个元素在\( ...
- [poj3074]Sudoku(舞蹈链)
题目链接:http://poj.org/problem?id=3074 舞蹈链精确覆盖的经典题目,一个数独每个位置的要求,可以得到以下四个约束1.每个位置有且只有一个数字2.每个位置的数字在一行只能出 ...
- luogu P4929 【模板】舞蹈链 DLX
LINK:舞蹈链 具体复杂度我也不知道 但是 搜索速度极快. 原因大概是因为 每次检索的时间少 有一定的剪枝. 花了2h大概了解了这个东西 吐槽一下题解根本看不懂 只能理解大概的想法 核心的链表不太懂 ...
- Vijos1755 靶形数独 Sudoku NOIP2009 提高组 T4 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求这个数独中所有的解法中的最大价值. 一个数独解法的价值之和为每个位置所填的数值 ...
- P4929-[模板]舞蹈链(DLX)
正题 题目链接:https://www.luogu.com.cn/problem/P4929 题目大意 \(n*m\)的矩形有\(0/1\),要求选出若干行使得每一列有且仅有一个\(1\). 解题思路 ...
- 关于用舞蹈链DLX算法求解数独的解析
欢迎访问——该文出处-博客园-zhouzhendong 去博客园看该文章--传送门 描述 在做DLX算法题中,经常会做到数独类型的题目,那么,如何求解数独类型的题目?其实,学了数独的构建方法,那么DL ...
随机推荐
- python-进程之间通信、多线程介绍
一.进程之间通信 进程的任务有三种状态:运行,就绪,阻塞. 加锁可以让多个进程修改同一块数据时,同一时间只能由一个任务可以进行修改,即串行的修改.牺牲了速度,保证了数据安全. 虽然可以使用文件共享数据 ...
- swift 学习- 25 -- 协议 02
// 通过扩展添加协议一致性 // 即便无法修改源代码, 依然可以通过扩展 令已有类型遵循并符合协议, 扩展可以为已有类型添加属性, 方法, 下标 以及构造器, 因此可以符合协议中的相应要求 // 注 ...
- Oracle Vm VirtualBox 搭建 yum 环境
配置本地yum库(用root用户操作) 创建挂载目录 #创建挂载目录 [root@oracle ~]# mkdir /mnt/cdrom # 查看挂载目录 [root@oracle ~]# ls /m ...
- Confluence 6 配置 XSRF 保护
Confluence 需要一个 XSRF 令牌才能创建一个评论,这个被用来保护用户不在评论区恶意发布内容.所有 Confluence 自定义的主题都被启用了这个功能,但是如果你使用自定义主题的话,可能 ...
- LeetCode(125):验证回文串
Easy! 题目描述: 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 示例 1: 输入: "A man, ...
- 获取表单内的所有元素的值 表单格式化插件jquery.serializeJSON
简单描述:一个form表单里有十几个input或者select,要获取到他们的值,我的做法一直都是$("#id").val();这样做本来没什么说的,但是如果有很多呢,就很麻烦,看 ...
- strchr()
strchr()主要有2个最有用的用法: 第一个:搜索字符串在另一字符串中的第一次出现.并返回剩余的部分 $str = "hello_chrdai_1993"; $not_incl ...
- 在线版区间众数 hzw的代码。。
/* 查询区间众数,要求强制在线 设有T个块 1.众数只可能在大块[L,R]里或者两端[l,L) (R,r]里出现 2.大块的众数只要预处理打表一下即可,复杂度n*T(这样的区间有T*T个) 3.两端 ...
- hdu1198 普通的并查集
今天开始(第三轮)并查集,,之前学的忘了一些 本题很简单直接上代码 #include<iostream> #include<cstring> #include<cstdi ...
- 【Vue】组件watch props属性值
转载: https://www.cnblogs.com/mqxs/p/8972368.html #HTML <div id="example"> <p> & ...