题目:Sudoku

匪夷所思的方法,匪夷所思的速度!!!

https://github.com/ttlast/ACM/blob/master/Dancing%20Link%20DLX/poj%203074.cpp

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int inf = ;
int flag;
typedef long long LL;
#define FF(i,A,s) for(int i = A[s];i != s;i = A[i])
const int maxm = ;
const int maxn = ;
int used[maxn];
struct DLX{
int R[maxm],L[maxm],U[maxm],D[maxm];
int col[maxm],row[maxm];
int s[maxn];bool hash[maxn]; //重复覆盖
int pre,first,sz,NV,limit;
void init(int n) //列的数目
{
int i;
for(i = ;i <= n;i ++)
{
U[i] = i;D[i] = i;
col[i] = i; //
L[i] = i-,R[i] = i+;
}
NV = n;sz = n+;pre = -;first = ;
memset(s,,sizeof(s));
}
void insert(int i,int j) //一行一行的插入数据i行j列
{
if(i != pre) //pre表示前一行,如果不同,就更新前面那行的左右
{
R[sz-] = first;L[first] = sz -;
pre = i;first = sz;
}
L[sz] = sz - ;R[sz] = sz+; //可以将j列看做矩阵的最底部.
D[U[j]] = sz;
D[sz] = j;U[sz] = U[j];U[j] = sz;
row[sz] = i,col[sz] = j,s[j] ++;
sz ++;
}
void finish() { R[sz-] = first;L[first] = sz - ;}
void EXremove(int c){ //删除c列,而且与c有重复的行精确覆盖
L[R[c]] = L[c];R[L[c]] = R[c];
FF(i,D,c) FF(j,R,i) U[D[j]] = U[j],D[U[j]] = D[j],--s[col[j]];
}
void EXresume(int c){ //恢复c列,而且与c有重复的行
FF(i,U,c) FF(j,L,i) ++s[col[j]],U[D[j]] = j,D[U[j]] = j;
L[R[c]] = c;R[L[c]] = c;
}
//选择行,使每一列仅有一个
bool dfs(const int &k) //精确覆盖,选择了k行了。
{
if(flag) return true;
//if(k >= flag) return false;
if(R[] == )
{
//if(flag > k) flag = k;
flag = ;
return true;
}
//if(R[0] == 0) return true; //找到解
int idx = R[],i;
for(i = R[] ;i != ;i = R[i]) if(s[idx] > s[i]) idx = i;
EXremove(col[idx]);
FF(i,D,idx){
used[row[i]] = ;
FF(j,R,i) EXremove(col[j]);
if(dfs(k+)) return true; //查找下一个。
FF(j,L,i) EXresume(col[j]);
used[row[i]] = ;
}
EXresume(col[idx]);
return false;
}
//重复覆盖,选择最少行,所有的列被覆盖,后来添加的。
void remove(int & c) { FF(i,D,c) L[R[i]] = L[i],R[L[i]] = R[i]; } //去掉某列
void resume(int & c) { FF(i,U,c) L[R[i]] = i,R[L[i]] = i; }
int h(){ //f启发函数
int ret = ;
memset(hash,false,sizeof(hash));
for(int c = R[];c != ;c = R[c]) if(!hash[c]){ //可以修改c != 0部分
hash[c] = true; ret ++;
FF(i,D,c)
FF(j,R,i) hash[col[j]] = true;
}
return ret;
}
//重复覆盖,只删除列不删除行
bool dfs(const int & k,int & limit)
{
if(k+h() >= limit) return false;
if(R[] == )
{
if(k < limit) limit = k; return true;
}
int idx = R[],i;
for(i = R[] ;i != ;i = R[i]) if(s[idx] > s[i]) idx = i;
FF(i,D,idx){
remove(i);
FF(j,R,i) remove(j);
if(dfs(k+,limit)) return true;
FF(j,L,i) resume(j);
resume(i);
}
return false;
}
int astar() //or 二分。
{
limit = h();
while(!dfs(,limit)) limit ++; //修改点,limit最后期限
return limit;
}
};
DLX dlx;
char c[];
int map[];
int main()
{
int i,j,k,pos,row,cnt;
while(gets(c))
{
if(c[] == 'e') break;
dlx.init();
row = ;
memset(used,,sizeof(used));
for(i = ;i < ;i ++)
for(j = ;j < ;j ++)
{
if(c[i*+j] == '.'){
for(k = ;k <= ;k ++)
{
dlx.insert(row,i*+k); //行+数字
dlx.insert(row,+j*+k); //列+数
dlx.insert(row,+(i/+(j/)*)*+k); //小方块号号
dlx.insert(row,+i*+j+); //座位
map[row++] = k;
}
}else{
cnt = c[i*+j] - '';
dlx.insert(row,i*+cnt); //行+数字
dlx.insert(row,+j*+cnt); //列+数
dlx.insert(row,+(i/+(j/)*)*+cnt); //小方块号
dlx.insert(row,+i*+j+); //座位
map[row++] = cnt;
}
}
dlx.finish();
flag = ;
if(dlx.dfs())
{
for(i = ;i < row;i ++)
if(used[i]) printf("%d",map[i]);
printf("\n");
}else puts("NO");
}
return ;
}

DLX (poj 3074)的更多相关文章

  1. POJ 3074 Sudoku (DLX)

    Sudoku Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Statu ...

  2. 搜索(DLX): POJ 3074 3076 Sudoku

    POJ 3074 : Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller ...

  3. POJ 3074 Sudoku DLX精确覆盖

    DLX精确覆盖.....模版题 Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8336   Accepted: ...

  4. (简单) POJ 3074 Sudoku, DLX+精确覆盖。

    Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgr ...

  5. POJ 3074 Sudoku (Dancing Links)

    传送门:http://poj.org/problem?id=3074 DLX 数独的9*9的模板题. 具体建模详见下面这篇论文.其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中 ...

  6. 【POJ 3074】 Sudoku

    [题目链接] http://poj.org/problem?id=3074 [算法] 将数独问题转化为精确覆盖问题,用Dancing Links求解 转化方法如下 : 我们知道,在一个数独中 : 1. ...

  7. POJ 3074 Sudoku(算竞进阶习题)

    二进制优化+dfs 话说这题数据中真的丧心病狂..不加inline还过不去.. 因为不会DLX只好用二进制来优化了...万万没想到还是低空飘过 我们在行.列.格分别用一个9位二进制常数来记录什么数能放 ...

  8. POJ 3074 Sudoku (Dacing Links)

    推荐一个写数独很好的博客:http://www.cnblogs.com/grenet/p/3163550.html 主要是把九宫格里的元素换到矩阵里面再求解dancing links 网上找的一模版 ...

  9. poj 3074 Sudoku(Dancing Links)

    Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8152   Accepted: 2862 Descriptio ...

随机推荐

  1. NDO to PNP( ndoutils to PNP4Nagios)

    How to use this script The aim of this script is to import your ndo database directly into PNP4nagio ...

  2. VC++ 简单的打印功能(对话框模式下)

    不多说,直接上代码 void CParamDlg::OnBnClickedButton6() { // TODO: 在此添加控件通知处理程序代码 CDC dc; CPrintDialog dlg(TR ...

  3. study notes for python

    some useful materials Python完全新手教程 http://www.cnblogs.com/taowen/articles/11239.aspx (from taowen, B ...

  4. JQuery 概况

  5. 详解收发不畅原因及U-Mail邮件中继解决之道

    邮件在商务往来中扮演着信息交流的重要角色,假如传输受阻,必将造成沟通不畅:可能三五封邮件的投递你意识不到其重要性,但假如长期需和客户保持沟 通,则需要保证其一贯的稳定性,这就很考验相关软件平台的性能是 ...

  6. oracle 数据库的学习1

    1.oracle 数据库常用的基本类型 char(10)  -->存储固定长度的字符串 varchar2(10)-->存储可变长的字符串 Date INTEGER -->存储整数 N ...

  7. QT征程之初识qt

    下载 https://www.qt.io/cn/download-open-source/     下载QT离线安装包 Qt 5.5.1 for Linux 32-bit (546 MB) (info ...

  8. 利用matlab摄像机标定

    (1)输入图像 "Image names"键 Matlab的图形窗口显示出20幅靶标图像 (2) 提取角点 "Extract grid corners"键. 输 ...

  9. Oracle 去除两边空格

    sql 去掉两头空格sql语法中没有直接去除两头空格的函数,但有ltrim()去除左空格rtrim()去除右空格.合起来用就是sql的trim()函数,即select ltrim(rtrim(UsrN ...

  10. PowerShell全自动分配CPU

    代码 $pro = Get-Process foreach ($n in $pro){ if($n.ProcessorAffinity -ne 255){ #continue } if($n.Id - ...