DLX算法求解精确覆盖问题模板。赛场上可以参见白书。

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int sub[10][10]={
{0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,2,2,2,3,3,3},
{0,1,1,1,2,2,2,3,3,3},
{0,1,1,1,2,2,2,3,3,3},
{0,4,4,4,5,5,5,6,6,6},
{0,4,4,4,5,5,5,6,6,6},
{0,4,4,4,5,5,5,6,6,6},
{0,7,7,7,8,8,8,9,9,9},
{0,7,7,7,8,8,8,9,9,9},
{0,7,7,7,8,8,8,9,9,9}
};
int hlb[12],hub[12],llb[12],lub[12];
const int maxn=4*9*9+5;
const int maxr=9*9*9+5;
const int maxnode=9*9*9*4+maxn+5;
//ÐбàºÅ´Ó1¿ªÊ¼£¬ÁбàºÅΪ1~n£¬½áµã0ÊDZíÍ·½áµã£»½áµã1~nÊǸ÷Áж¥²¿µÄÐéÄâ½áµã
struct DLX{
int n,sz;//ÁÐÊý£¬½áµã×ÜÊý
int S[maxn];//¸÷ÁнáµãÊý
int row[maxnode],col[maxnode];//¸÷½áµãËùÔÚµÄÐÐÁбàºÅ
int L[maxnode],R[maxnode],U[maxnode],D[maxnode];
int ansd,ans[maxr];//½â
void init(int n){//nÊÇÁÐÊý
this->n=n;
for(int i=0;i<=n;++i){
U[i]=i;
D[i]=i;
L[i]=i-1;
R[i]=i+1;
}
R[n]=0; L[0]=n;
sz=n+1;
memset(S,0,sizeof(S));
}
void addRow(int r,vector<int> columns){
int first=sz;
for(int i=0;i<columns.size();++i){
int c=columns[i];
L[sz]=sz-1;
R[sz]=sz+1;
D[sz]=c;
U[sz]=U[c];
D[U[c]]=sz;
U[c]=sz;
row[sz]=r;
col[sz]=c;
++S[c];
++sz;
}
R[sz-1]=first;
L[first]=sz-1;
}
//˳×ÅÁ´±íA£¬±éÀú³ýsÍâµÄÆäËûÔªËØ
#define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])
void remove(int c){
L[R[c]]=L[c];
R[L[c]]=R[c];
FOR(i,D,c){
FOR(j,R,i){
U[D[j]]=U[j];
D[U[j]]=D[j];
--S[col[j]];
}
}
}
void restore(int c){
FOR(i,U,c){
FOR(j,L,i){
++S[col[j]];
U[D[j]]=j;
D[U[j]]=j;
}
}
L[R[c]]=c;
R[L[c]]=c;
}
bool dfs(int d){
// printf("%d",d);
if(R[0]==0){//ÕÒµ½½â
ansd=d;//¼Ç¼½âµÄ³¤¶È
return 1;
}
//ÕÒ½áµãÊý×îСµÄÁÐc
int c=R[0];//µÚÒ»¸öδɾ³ýµÄÁÐ
FOR(i,R,0){
if(S[i]<S[c]){
c=i;
}
}
remove(c);//ɾ³ýµÚcÁÐ
FOR(i,D,c){//ÓýáµãiËùÔÚÐи²¸ÇµÚcÁÐ
ans[d]=row[i];
FOR(j,R,i){
remove(col[j]);//ɾ³ý½áµãiËùÔÚÐÐÄܸ²¸ÇµÄËùÓÐÆäËûÁÐ
}
if(dfs(d+1)){
return 1;
}
FOR(j,L,i){
restore(col[j]);//»Ö¸´½áµãiËùÔÚÐÐÄܸ²¸ÇµÄÆäËûËùÓÐÁÐ
}
}
restore(c);//»Ö¸´µÚcÁÐ
return 0;
}
bool solve(vector<int>& v){
v.clear();
if(!dfs(0)){
return 0;
}
for(int i=0;i<ansd;++i){
v.push_back(ans[i]);
}
return 1;
}
}dlx;
char s[12][12];
int a[12][12];
int mah[1005],mal[1005],mav[1005];
int encode(int a,int b,int c){
return a*81+b*9+c+1;
}
void decode(int code,int &a,int &b,int &c){
--code;
c=code%9;code/=9;
b=code%9;code/=9;
a=code;
}
int main(){
int zu;
// freopen("poj2676.in","r",stdin);
// freopen("poj2676.out","w",stdout);
memset(hlb,0x7f,sizeof(hlb));
memset(llb,0x7f,sizeof(llb));
for(int i=1;i<=9;++i){
for(int j=1;j<=9;++j){
hlb[sub[i][j]]=min(hlb[sub[i][j]],i);
hub[sub[i][j]]=max(hub[sub[i][j]],i);
llb[sub[i][j]]=min(llb[sub[i][j]],j);
lub[sub[i][j]]=max(lub[sub[i][j]],j);
}
}
scanf("%d",&zu);
for(;zu;--zu){
for(int i=1;i<=9;++i){
scanf("%s",s[i]+1);
}
int hang=0,lie=0;
for(int i=1;i<=9;++i){
for(int j=1;j<=9;++j){
a[i][j]=s[i][j]-'0';
}
}
dlx.init(9*9*4);
for(int i=1;i<=9;++i){
for(int j=1;j<=9;++j){
for(int k=1;k<=9;++k){
if(!a[i][j] || a[i][j]==k){
vector<int> columns;
columns.push_back(encode(0,i-1,j-1));
columns.push_back(encode(1,i-1,k-1));
columns.push_back(encode(2,j-1,k-1));
columns.push_back(encode(3,sub[i][j]-1,k-1));
dlx.addRow(encode(i-1,j-1,k-1),columns);
}
}
}
}
vector<int> ans;
dlx.solve(ans);
for(int i=0;i<ans.size();++i){
int r,c,v;
decode(ans[i],r,c,v);
a[r+1][c+1]=v+1;
}
for(int i=1;i<=9;++i){
for(int j=1;j<9;++j){
printf("%d",a[i][j]);
}
printf("%d\n",a[i][9]);
}
}
return 0;
}

【DLX算法】poj2676 Sudoku的更多相关文章

  1. 搜索:DLX算法

    精确覆盖问题:在一个0-1矩阵中,选定部分行,使得每一列都有且只有一个1.求解一种选法 舞蹈链(Dance Link),也就是一个循环十字链表,可以快速的删掉和恢复某行某列 结合了舞蹈链的搜索就称作D ...

  2. poj2676 Sudoku(DFS)

    做了很久还是参考了别人的答案orz,其实也不难啊.我要开始学一下怎么写搜索了... 题目链接:poj2676 Sudoku 题解:暴力搜索,DFS每个空白格子所放数字. #include<cst ...

  3. 关于用舞蹈链DLX算法求解数独的解析

    欢迎访问——该文出处-博客园-zhouzhendong 去博客园看该文章--传送门 描述 在做DLX算法题中,经常会做到数独类型的题目,那么,如何求解数独类型的题目?其实,学了数独的构建方法,那么DL ...

  4. 【DLX算法】hdu3498 whosyourdaddy

    题意:给你一个01矩阵,让你选择尽可能少的行数,使得这些行的并集能够覆盖到所有列. DLX算法求解重复覆盖问题模板,使用估价函数进行剪枝. #include<cstdio> #includ ...

  5. POJ2676 Sudoku 舞蹈链 DLX

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求解.SPJ 题解 DLX + 矩阵构建  (两个传送门) 代码 #includ ...

  6. [leetcode]算法题目 - Sudoku Solver

    最近,新加坡总理李显龙也写了一份代码公布出来,大致瞧了一眼,竟然是解数独题的代码!前几天刚刚写过,数独主要算法当然是使用回溯法.回溯法当时初学的时候在思路上比较拧,不容易写对.写了几个回溯法的算法之后 ...

  7. DLX算法一览

    目录: 1 X思想的了解. 链表的递归与回溯. 具体操作. 优化. 一些应用与应用中的再次优化(例题). 练手题 X思想的了解. 首先了解DLX是什么? DLX是一种多元未饱和型指令集结构,DLX 代 ...

  8. poj2676 Sudoku

    Sudoku Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17953   Accepted: 8688   Special ...

  9. [DLX]HDOJ4069 Squiggly Sudoku

    题意:有9*9的格子 每个格子 由五部分组成:上(16).右(32).下(64).左(128).和该格的数值(0~9) 若上下左右有分割格子的线 就加上相应的数, 该格的数值若为0,则是未知  1~9 ...

随机推荐

  1. 超级ping(多线程版)

    发现学校公共wifi的ip段是10.1.0-255.0-255段的,还是之前的思路批量ping一波. 其实可以使用nmap的.但是脚本写都写了.是吧.你懂的. #!/usr/bin/env pytho ...

  2. 转:修改shape的文字

    Sub 修改shape的文字()'' 修改shape的文字 宏' '    ActiveSheet.Shapes.Range(Array("Flowchart: Connector 193& ...

  3. sicily 1193. Up the Stairs

    Time Limit: 1sec    Memory Limit:32MB  Description John is moving to the penthouse of a tall sky-scr ...

  4. Nim 游戏、SG 函数、游戏的和

    Nim游戏 Nim游戏定义 Nim游戏是组合游戏(Combinatorial Games)的一种,准确来说,属于“Impartial Combinatorial Games”(以下简称ICG).满足以 ...

  5. 设计模式之笔记--享元模式(Flyweight)

    享元模式(Flyweight) 定义 享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象. 类图 描述 Flyweight:抽象享元类,是所有的具体享元类的基类,为子类规定出需要实 ...

  6. ssh使两台机器建立连接

    ssh利用口令建立连接过程: 客户端--> 发送连接请求 --> 远程主机 --> 返回远程主机的公钥 --> 公钥加密客户端私钥+客户端公钥返回远程主机 --> 远程主 ...

  7. PSQueue队列操作

    队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈(FILO,First In Last Out,先进后出)属于线性表一样,队 ...

  8. 1.第一个hello word

    1.生产者 #!/usr/bin/env python import pika connection = pika.BlockingConnection(pika.ConnectionParamete ...

  9. Codeforces 798D - Mike and distribution(二维贪心、(玄学)随机排列)

    题目链接:http://codeforces.com/problemset/problem/798/D 题目大意:从长度为n的序列A和序列B中分别选出k个下表相同的数要求,设这两个序列中k个数和分别为 ...

  10. hdu 1597(矩阵快速幂)

    1597: 薛XX后代的IQ Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 228  Solved: 55[Submit][Status][Web Bo ...