题意:解数独

分析:

完整的数独有四个充要条件:

1.每个格子都有填数字

2.每列都有1~9中的每个数字

3.每行都有1~9中的每个数字

4.每个9宫格都有1~9中的每个数字

可以转化成精确覆盖问题。每行表示一个格子的一种填法,1~81列表示这个格子的位置,82~162列表示这是哪一行的什么数字,163~243列表示这是哪一列的什么数字,244~324列表示这是哪一个九宫格里的什么数字。每行都把四个1填入这四个区间里的对应位置。最后求出这个01矩阵的精确覆盖就是解。

对于已经确定的点 我们就直接建一行 对于没有确定的点我们就 建k行(k<=9),这样说如果在该行该列或者该3*3的矩阵中存在该数字 则对应的该数字所在的行就没有必要建立了

这样跑一次dlx精确覆盖就ok了

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <string.h>
using namespace std;
const int M=****; struct node{
int c,x,y,k;
};
struct DLX
{
int n,sz;
int S[**];
int row[M],col[M];
int L[M],R[M],U[M],D[M];
int ans[][];
int X[M],Y[M],Cnt[M];
void init(int n)
{
this->n=n;
for(int i=; i<=n; i++)
{
U[i]=i;D[i]=i;
L[i]=i-; R[i]=i+;
}
R[n]=;L[]=n;
sz=n+;
memset(S,,sizeof(S));
}
void addRow(int r,vector<node>columns)
{
int first=sz;
for(int i=; i<columns.size();i++)
{
int c=columns[i].c; X[sz]=columns[i].x; Y[sz]=columns[i].y; Cnt[sz]=columns[i].k;
L[sz]=sz-;
R[sz]=sz+;
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-]=first; L[first]=sz-;
}
#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[]==)return true;
else
{
int num=R[];
FOR(i,R,)
{
if(S[i]==) return false;
if(S[num]>S[i])
{
num=i;
}
}
remove(num);
FOR(i,D,num)
{
ans[X[i]][Y[i]]=Cnt[i];
FOR(j,R,i)remove(col[j]);
if(dfs(i+))
{
return true;
}
FOR(j,L,i)restore(col[j]);
}
restore(num);
return false;
}
}
}Link;
bool hasr[][],hasc[][],hasp[][];
char str[];
vector<node> colum;
int main()
{
while(scanf("%s",str)==&&str[]!='e')
{
memset(hasr,false,sizeof(hasr));
memset(hasc,false,sizeof(hasc));
memset(hasp,false,sizeof(hasp));
for(int i=; i<; i++)
for(int j=; j<; j++)
{
if(str[i*+j]!='.')
{
int k=str[i*+j]-'';
hasr[i][k]=true;
hasc[j][k]=true;
hasp[i/ *+j/][k]=true;
}
}
int m=**;
int n=;
Link.init(m);
for(int i=; i<; i++)
for(int j=; j<; j++)
{
int k=;
if(str[i*+j]!='.')
k=str[i*+j]-'';
if(k!=)
{
n++;
colum.clear();
node dot;
dot.k=k;
dot.x=i;
dot.y=j;
dot.c=i*+j+;
colum.push_back(dot);
dot.c=+i*+k;
colum.push_back(dot);
dot.c=+j*+k;
colum.push_back(dot);
dot.c=+(i/*+j/)*+k;
colum.push_back(dot);
Link.addRow(n,colum);
}else {
node dot;
dot.x=i;dot.y=j;
for(int k=; k<=; k++)
{
if(hasr[i][k]==false &&hasc[j][k]==false && hasp[i/*+j/][k]==false)
{
dot.k=k;
colum.clear();
n++;
dot.c=i*+j+;
colum.push_back(dot);
dot.c=+i*+k;
colum.push_back(dot);
dot.c=+j*+k;
colum.push_back(dot);
dot.c=+(i/*+j/)*+k;
colum.push_back(dot);
Link.addRow(n,colum);
}
} } }
Link.dfs();
for(int i=; i<;i++)
for(int j=; j<; j++)
printf("%d",Link.ans[i][j]);
puts("");
}
return ;
}

poj3074 DLX精确覆盖的更多相关文章

  1. 【转】DLX 精确覆盖 重复覆盖

    问题描述: 给定一个n*m的矩阵,有些位置为1,有些位置为0.如果G[i][j]==1则说明i行可以覆盖j列. Problem: 1)选定最少的行,使得每列有且仅有一个1. 2)选定最少的行,使得每列 ...

  2. POJ 3076 Sudoku DLX精确覆盖

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

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

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

  4. (简单) HUST 1017 Exact cover , DLX+精确覆盖。

    Description There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is ...

  5. DLX精确覆盖与重复覆盖模板题

    hihoCoder #1317 : 搜索四·跳舞链 原题地址:http://hihocoder.com/problemset/problem/1317 时间限制:10000ms 单点时限:1000ms ...

  6. POJ 3074 Sudoku DLX精确覆盖

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

  7. zoj 3209.Treasure Map(DLX精确覆盖)

    直接精确覆盖 开始逐行添加超时了,换成了单点添加 #include <iostream> #include <cstring> #include <cstdio> ...

  8. [DLX精确覆盖] hdu 1603 A Puzzling Problem

    题意: 给你n块碎片,这些碎片不能旋转.翻折. 问你能不能用当中的某些块拼出4*4的正方形. 思路: 精确覆盖裸题了 建图就是看看每一个碎片在4*4中能放哪些位置,这个就作为行. 列就是4*4=16个 ...

  9. HUST 1017 Exact cover(DLX精确覆盖)

    Description There is an N*M matrix with only 0s and 1s, (1 <= N,M <= 1000). An exact cover is ...

随机推荐

  1. 20165225《Java程序设计》第五周学习总结

    20165225<Java程序设计>第五周学习总结 1.视频与课本中的学习: - 第七章学习总结 内部类: 内部类的外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外嵌类中的方 ...

  2. linux常用查看文件或日志命令

    常见查看文件内容命令汇总如下: cat     filename           查看日志,会打开整个文件,直接跑到最后面 tac     filename           查看日志,会打开整 ...

  3. AT3611 Tree MST 点分治+最小生成树

    正解:点分治+最小生成树 解题报告: 传送门! 然后这题麻油翻译,,,所以这边的建议是先说下题意呢亲 所以题意大概就是说,给一棵n个节点的树,树上每个点都有个权值,然后构造一个完全图,(u,v)之间连 ...

  4. python中由于中文路径引起的os.path.isfile(imgpath) == False问题

    昨天在用python脚本处理文件的时候,遇到了题述问题,明明文件时存在的,但是在用os.path.isfile(imgpath) == False进行判断的时候总是成立,在一开始以为是正反斜杠wind ...

  5. 使用poi读写excel文件

    使用poi库测试了一下读取excel文件,效果不错,跟大家分享一下. 第一列是数值型,第二列是字符型,代码如下: package poi; import java.io.FileInputStream ...

  6. windows下安装Git安装

    一:Git是什么? Git是一个代码仓库,属于分散型版本管理系统. 二:在windows下安装Git 载msysgit 1. 访问 msysGit 的项目主页,下载 msysGit.http://ms ...

  7. LigerUi折叠与展开

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...

  8. vue中的路由高亮

  9. 遇到Visual Studio "当前不会命中断点.还没有为该文档加载任何符号"的情况

    一.问题及原因 有这样一种调用逻辑:A.exe调用B.dll.现在想要在B的源代码中打断点,从A发起进行调试,却给出了"当前不会命中断点.还没有为该文档加载任何符号"的提示.感觉十 ...

  10. [redis]redis常用

    https://redis.io/topics/quickstart $ redis-cli ping PONG redis-server is the Redis Server itself. re ...