题目: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. 自动备份SQL数据库 并删除指定日期之前的备份文件

    /// <summary>        /// 数据备份        /// </summary>        /// public bool DataBackup(st ...

  2. the server quit without updating pid file (/var/lib/mysql/localhost.localdomain.pid)

    前几天装的mysql,用的还挺爽的,第二天再用就不行了,报的错误如标题.网上也是众说纷纭,可能有很多原因会导致这种错误吧.我用的是将Mysqld这个进程杀掉,就可以启动mysql了

  3. Loadrunner不能调用IE解决方法大全

    在使用loadrunner进行性能调试时,录制脚本的时候,发现loadrunner不能调用IE.不能自动启动IE,还有一种情况是可以启动,但是录制不到内容,action的内容为空. 一般遇到这种情况, ...

  4. Android菜鸟成长记13 -- 初识application

    二.Application 简介 Application 类是用来维护应用程序全局状态.你可以提供自己的实现,并在 AndroidManifest.xml文件的 <application> ...

  5. Linux下MySQL数据库常用基本操作 一

    1.显示数据库 show databases; 2.选择数据库 use 数据库名; 3.显示数据库中的表 show tables; 4.显示数据表的结构 describe 表名; 5.显示表中记录 S ...

  6. php调用阿里大鱼 接口curl

    function http_request($url, $data = null, $header = null, $method = 'GET') { //如果是Get传参,拼接字符串 if ($m ...

  7. 把cmd信息中的正常和异常输出分别输出到不同txt文件中

    场景一: 1.大量滚动信息容纳不下,在小黑屏中被冲刷掉. 2.希望把正常输出和异常输出分别输出到不同地方. 相关命令 一共有4个输出到文件的命令,现以jar命令打war包举例说明: 命令 说明 举例  ...

  8. 通过RGB灯输出七色

    本文由博主原创,如有不对之处请指明,转载请说明出处. /********************************* 代码功能:输出模拟信号,控制RGB灯的颜色 使用函数: pinMode(引脚 ...

  9. ng-repeat产生的对象会带有$$hashkey属性处理方法

    angularJS在ng-repeat的时候会产生一个$$hashkey的属性向后台发送请求的时候需要转成JSON的string格式(如果是使用ng自带的$http服务的话可以无视,$http服务会自 ...

  10. .net妹纸转Java---java环境的搭建,myeclipse10.0 的安装环境变量配置和破解

    啦啦啦 ,因为公司项目需要,从我大火炉--大武汉被拖到了更大的火炉--大广西  其实一开始 我的内心是拒绝的. 但是我在大武汉呆了近2年木有出过远门,对, 生活除了眼前的苟且,还有远方的苟且.怀揣这样 ...