poj3074-Sodoku
解数独。
分析
考虑如何把数独解合法的条件转化为经典的01精确覆盖:
- 每个格子只能填一个数,1-9
- 每一列刚好填了1-9
- 每一行刚好填了1-9
- 每个九宫格刚好填了1-9
也就是说,每个格子,列,行,九宫格都需要被一个数覆盖,且不能重复覆盖。
精确覆盖的一个很巧妙的,也很常用的建矩阵方法,是把条件拆开,把每一个填入也拆成对四种条件的贡献。
也就是说,我们建一个729*324的矩阵。所有的行表示在\((x,y)\)填入\(k\),前81列表示每个格子被覆盖,后面的各81列分别表示每一列,一行,九宫格被覆盖,那么这就是一个精确覆盖问题了——每次填入一个数,可以对应地在四个规则中产生贡献。
如果已经给到有数了,那么就\((x,y)\)就只能填入规定的那个\(k\),否则可以填1-9。
代码
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=10*10*10;
const int maxm=10*10*5;
const int maxl=10*10;
const int maxp=maxn*maxm;
bool a[maxn][maxm];
char s[maxl];
int ans[10][10];
struct node {
int l,r,u,d,row,col;
};
int id(int x,int y) {
return (x-1)*9+y;
}
int hang(int x,int k) {
return 81+(x-1)*9+k;
}
int lie(int y,int k) {
return 162+(y-1)*9+k;
}
int bel(int x,int y) {
return ((x-1)/3)*3+(y-1)/3+1;
}
int gong(int x,int y,int k) {
return 243+(bel(x,y)-1)*9+k;
}
int choose(int x,int y,int k) {
return (id(x,y)-1)*9+k;
}
void ANS(int row) {
int k=(row-1)%9+1;
row-=k;
int d=row/9+1;
int y=(d-1)%9+1;
int x=(d-y)/9+1;
ans[x][y]=k;
}
struct DLX {
node p[maxp];
int tot,last[maxm],size[maxm];
void clear(int n) {
tot=n;
memset(p,0,sizeof p),memset(last,0,sizeof last),memset(size,0,sizeof size);
p[0]=(node){n,1,0,0,0,0};
for (int i=1;i<=n;++i) p[i]=(node){i-1,i+1,i,i,0,i},last[i]=i;
p[n].r=0;
}
void build(int row,int c[],int len) {
if (!len) return;
p[++tot]=(node){tot,tot,last[c[1]],p[last[c[1]]].d,row,c[1]};
p[p[tot].u].d=p[p[tot].d].u=last[c[1]]=tot;
++size[p[tot].col];
for (int i=2;i<=len;++i) {
int x=c[i];
p[++tot]=(node){tot-1,p[tot-1].r,last[x],p[last[x]].d,row,x};
p[p[tot].l].r=p[p[tot].r].l=p[p[tot].d].u=p[p[tot].u].d=last[x]=tot;
++size[p[tot].col];
}
}
void del(int c) {
p[p[c].l].r=p[c].r,p[p[c].r].l=p[c].l;
for (int i=p[c].d;i!=c;i=p[i].d)
for (int j=p[i].r;j!=i;j=p[j].r)
p[p[j].u].d=p[j].d,p[p[j].d].u=p[j].u,--size[p[j].col];
}
void back(int c) {
p[p[c].l].r=p[p[c].r].l=c;
for (int i=p[c].u;i!=c;i=p[i].u)
for (int j=p[i].l;j!=i;j=p[j].l)
p[p[j].u].d=p[p[j].d].u=j,++size[p[j].col];
}
bool dance() {
if (!p[0].r) return true;
int first=p[0].r;
for (int i=p[0].r;i;i=p[i].r) if (size[i]<size[first]) first=i;
if (p[first].d==first) return false;
del(first);
for (int i=p[first].d;i!=first;i=p[i].d) {
for (int j=p[i].r;j!=i;j=p[j].r) del(p[j].col);
ANS(p[i].row);
if (dance()) return true;
for (int j=p[i].l;j!=i;j=p[j].l) back(p[j].col);
}
back(first);
return false;
}
} dlx;
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
while (~scanf("%s",s+1)) {
dlx.clear(324);
memset(a,0,sizeof a),memset(ans,0,sizeof ans);
if (s[1]=='e') break;
for (int i=1,k=0;i<=9;++i) for (int j=1;j<=9;++j) {
int x=(s[++k]=='.'?0:s[k]-'0'),st=(x?x:1),ed=(x?x:9);
ans[i][j]=x;
for (int k=st;k<=ed;++k) {
int cho=choose(i,j,k);
a[cho][id(i,j)]=a[cho][hang(i,k)]=a[cho][lie(j,k)]=a[cho][gong(i,j,k)]=true;
}
}
for (int i=1;i<=729;++i) {
static int c[maxm];
int tot=0;
for (int j=1;j<=324;++j) if (a[i][j]) c[++tot]=j;
dlx.build(i,c,tot);
}
dlx.dance();
for (int i=1;i<=9;++i) for (int j=1;j<=9;++j) printf("%d",ans[i][j]);
puts("");
}
return 0;
}
poj3074-Sodoku的更多相关文章
- POJ3074 Sudoku
POJ3074 Sudoku 与POJ2676相比,这一题搜索时每一步都找到最好确定的点进行枚举 对于每行.每列.每个九宫格,都分别用一个9位二进制数保存还有那些数还可以填 对于每个位置,将其所在行. ...
- POJ3074 Sudoku 舞蹈链 DLX
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求解. 题解 DLX + 矩阵构建 (两个传送门) 代码 #include & ...
- poj3074 DLX精确覆盖
题意:解数独 分析: 完整的数独有四个充要条件: 1.每个格子都有填数字 2.每列都有1~9中的每个数字 3.每行都有1~9中的每个数字 4.每个9宫格都有1~9中的每个数字 可以转化成精确覆盖问题. ...
- POJ3074 Sudoku(lowbit优化搜索)
In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For exa ...
- POJ3074 Sudoku 剪枝深(神?)搜
emm...挺秀的...挺神的? 每行,每列,每宫用一个二进制数表示选或没选的状态,刚开始设没选为1,然后更改状态的时候异或一下就好了: 这样可以通过lowbit取出每一个没有选过的数:(妙啊? 关于 ...
- POJ3074 Sudoku —— Dancing Links 精确覆盖
题目链接:http://poj.org/problem?id=3074 Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissio ...
- 数独(深搜)(poj2726,poj3074)
数独(深搜)数据最弱版本(poj 2676) Description Sudoku is a very simple task. A square table with 9 rows and 9 co ...
- 【POJ3074】Sudoku DLX(Dancing Links)
数独就要DLX,不然不乐意. 数独的DLX构造:9*9个点每一个点有9种选择,这构成了DLX的729行,每行.列.阵有限制,均为9行(/列/阵),然后每行(/列/阵)都有九种数的情况.于是就有了3*9 ...
- [poj3074]Sudoku(舞蹈链)
题目链接:http://poj.org/problem?id=3074 舞蹈链精确覆盖的经典题目,一个数独每个位置的要求,可以得到以下四个约束1.每个位置有且只有一个数字2.每个位置的数字在一行只能出 ...
- 【Dancing Link专题】解题报告
DLX用于优化精确覆盖问题,由于普通的DFS暴力搜索会超时,DLX是一个很强有力的优化手段,其实DLX的原理很简单,就是利用十字链表的快速删除和恢复特点,在DFS时删除一些行和列以减小查找规模,使得搜 ...
随机推荐
- 北京Uber优步司机奖励政策(1月18日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- P1011 车站
P1011 车站 题目描述 火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上.下车,但上.下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为 ...
- SpringBoot-05:SpringBoot初运行以及tomcat端口号的修改
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 上篇博客讲了,如何创建SpringBoot工程,所以,我本篇博客讲述,如何跑起来自己的第一个案例 1.准备一个 ...
- hdu1596find the safest road(floyd)
find the safest road Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- beauifulsoup模块的介绍
01 爬虫基础知识介绍 相关库:1.requests,re 2.BeautifulSoup 3.hackhttp 使用requests发起get,post请求,获取状态码,内容: 使用re匹 ...
- 获取App的PackageName包名和LauncherActivity启动页
第一种情况: 查看手机里面已经安装的App: 用数据线连接手机, 打开开发者模式, 并赋予相关权限: 1. 清除日志: adb logcat -c 2. 启动日志: adb logcat Activi ...
- 现实世界中的 Python
Python 有多稳定? 非常稳定. 自 1991 年起大约每隔 6 到 18 个月就会推出新的稳定发布版,这种状态看来还将持续下去. 目前主要发布版本的间隔通常为 18 个月左右. 开发者也会推出旧 ...
- Spring Cloud(五):Hystrix 监控面板【Finchley 版】
Spring Cloud(五):Hystrix 监控面板[Finchley 版] 发表于 2018-04-16 | 更新于 2018-05-10 | 在上一篇 Hystrix 的介绍中,我们提到 ...
- jdbc连接sql server2017进行简单的增、删、改、查操作
这几天刚做完数据库的课程设计,来稍微总结一下如何通过jdbc访问sql server数据库进行简单的增删改查操作.在连接之前,需要简单地配置一下,包括下载对应jdk版本的驱动,设置环境变量等等.相关配 ...
- 【jmeter进阶之逻辑控制器】
jmeter进阶之逻辑控制器 转载 https://www.cnblogs.com/malinalian/p/10491946.html 常用的逻辑控制器 1,循环控制器:可以设置该控制器内 ...