DLX算法,刚接触,是关于精确覆盖的,白书上有算法介绍。

代码模板

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std; char puzzle[20][20];
const int SLOT=0;
const int ROW=1;
const int COL=2;
const int SUB=3;
const int maxn=1300;
const int maxnode=256*16*4;
const int maxr=256*16*4; 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[maxn]; // 解 void init(int 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> c1)
{
int first = sz;
for(int i = 0 ; i < c1.size(); i++ ){
int c = c1[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){
if(R[0] == 0 ){
ansd = d;
return true;
}
// 找S最小的列c
int c = R[0] ;
FOR(i,R,0) if(S[i] < S[c]) c = i; remove(c);
FOR(i,D,c){
ans[d] = row[i];
FOR(j,R,i) remove(col[j]);
if(dfs(d + 1)) return true;
FOR(j,L,i) restore(col[j]);
}
restore(c); return false;
}
bool solve(vector<int> & v){
v.clear();
if(!dfs(0)) return false;
for(int i = 0 ; i< ansd ;i ++ ) v.push_back(ans[i]);
return true;
}
};
DLX slover; int encode(int a,int b,int c){
return a*256+b*16+c+1;
} void decode(int code,int &a,int &b,int &c){
code--;
c=code%16; code/=16;
b=code%16; code/=16;
a=code;
} bool read(){
for(int i=0;i<16;i++){
if(scanf("%s",puzzle[i])!=1) return false;
}
return true;
} int main(){
int kase=0;
while(read()){
if(++kase!=1) printf("\n");
slover.init(1024);
for(int r=0;r<16;r++){
for(int c=0;c<16;c++){
for(int v=0;v<16;v++){
if(puzzle[r][c]=='-'||puzzle[r][c]=='A'+v){
vector<int> columns;
columns.clear();
columns.push_back(encode(SLOT,r,c));
columns.push_back(encode(ROW,r,v));
columns.push_back(encode(COL,c,v));
columns.push_back(encode(SUB,(r/4)*4+c/4,v));
slover.addRow(encode(r,c,v),columns);
}
}
}
}
vector<int>ans;
// cout<<"YES"<<endl;
ans.clear();
slover.solve(ans);
// cout<<"YES"<<endl;
for(int i=0;i<ans.size();i++){
int r,c,v;
decode(ans[i],r,c,v);
puzzle[r][c]='A'+v;
}
for(int i=0;i<16;i++)
printf("%s\n",puzzle[i]);
}
return 0;
}

  

POJ 3076的更多相关文章

  1. (简单) POJ 3076 Sudoku , DLX+精确覆盖。

    Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells ...

  2. 【POJ 3076】 Sudoku

    [题目链接] http://poj.org/problem?id=3076 [算法] 将数独问题转化为精确覆盖问题,用Dancing Links求解 [代码] #include <algorit ...

  3. POJ 3076 Sudoku DLX精确覆盖

    DLX精确覆盖模具称号..... Sudoku Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 4416   Accepte ...

  4. POJ 3076 Sudoku

    3076 思路: dfs + 剪枝 首先,如果这个位置只能填一种字母,那就直接填 其次,如果对于每一种字母,如果某一列或者某一行或者某一块只能填它,那就填它 然后,对于某个位置如果不能填字母了,或者某 ...

  5. POJ 3076 / ZOJ 3122 Sudoku(DLX)

    Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells ...

  6. POJ 3076 Sudoku (dancing links)

    题目大意: 16*16的数独. 思路分析: 多说无益. 想说的就是dancing links 的行是依照 第一行第一列填 1 第一行第二列填 2 -- 第一行第十五列填15 第一行第二列填 1 -- ...

  7. Sudoku POJ - 3076

    Sudoku Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 5769   Accepted: 2684 Descripti ...

  8. Sudoku POJ - 3076 (dfs+剪枝)

    Description A Sudoku grid is a 16x16 grid of cells grouped in sixteen 4x4 squares, where some cells ...

  9. POJ 3076 SUKODU [Dangcing Links DLX精准覆盖]

    和3074仅仅有数目的不同,3074是9×9.本来想直接用3074的.然后MLE,,,就差那么20M的空间,,. 从这里学习到了解法: http://www.cnblogs.com/ylfdrib/a ...

随机推荐

  1. 操作系统-虚拟机-百科:VM

    ylbtech-操作系统-虚拟机-百科:VM 虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统. 虚拟系统通过生成现有操作系统的 ...

  2. HTML 14 JS事件

    一 :什么是事件 发生的某一件事:触发特定的条件,完成某一项功能 二:学习的目的 在特定的条件下,完成特定的功能 条件满足的情况下,系统会自动执行 ( 回调 ) 绑定的方法 学习要点: 1.事件的两种 ...

  3. Python 39 数据库的数据类型

    一:整型 为什么需要 数据分类? 1.为了描述事物更加准确 2.描述起来更方便 3.节省内存空间 例:1 a 你     utf8 下 5个字节 1 a b c   unicode 6个字节 mysq ...

  4. Redis(三)-Ubuntu下安装

    Ubuntu 下安装 在 Ubuntu 系统安装 Redi 可以使用以下命令: $sudo apt-get update $sudo apt-get install redis-server 启动 R ...

  5. android 可拖动控件 ontouchevent

    首先附上文章的转载内容的链接: 学习android 可拖动事件首先需要对android的屏幕和touchevent参数建立一个详细的知识结构. 1.android坐标系统 一.首先明确一下 andro ...

  6. cocos2d-x https

    cocos2d-x :2.1.3HttpClient.cpp文件中  bool configureCURL(CURL *handle)后边添加如下两句: curl_easy_setopt(handle ...

  7. Discuze修改用户名长度限制

    第一步,在网站 uc_client\model 目录下的 user.php文件中,找到如下代码: ? 1 if($len > 15 || $len < 3 || preg_match(&q ...

  8. Combotree--别样的构建层级json字符串

    1.先看效果 2.需要使用层级json格式,如: 3.先不要着急怎么去实现它,先来想想怎么用对象来描述它 4.代码 protected void Page_Load(object sender, Ev ...

  9. 努比亚 Z17 mini s (Nubia NX589J) 解锁BootLoader 并刷入recovery ROOT

    首先下载好工具链接:链接:https://pan.baidu.com/s/1gher4T9 密码:rypn 备用下载链接:https://pan.baidu.com/s/1nxdzt9Z 本篇教程教你 ...

  10. 【SQL】BETWEEN操作符

    BETWEEN 操作符在 WHERE 子句中使用,作用是选取介于两个值之间的数据范围. 操作符 BETWEEN ... AND 会选取介于两个值之间的数据范围.这些值可以是数值.文本或者日期. 注意: ...