poj 3074
题意:解数独
分析:
完整的数独有四个充要条件:
1.每个格子都有填数字
2.每列都有1~9中的每个数字
3.每行都有1~9中的每个数字
4.每个9宫格都有1~9中的每个数字
可以转化成精确覆盖问题。每行表示一个格子的一种填法,1~81列表示这个格子的位置,82~162列表示这是哪一行的什么数字,163~243列表示这是哪一列的什么数字,244~324列表示这是哪一个九宫格里的什么数字。每行都把四个1填入这四个区间里的对应位置。最后求出这个01矩阵的精确覆盖就是解。
在DFS里删除列的顺序为由左往右时TLE了,由右向左却AC,什么原因???
- #include <cstdio>
- #include <cstring>
- int U[],D[],L[],R[],row[],col[],cont[];
- int X[],Y[],H[],S[],M,N,sz,ans[][];
- bool hashr[][],hashc[][],hashp[][];
- void init(int m)
- {
- for(int i = ;i <= m;i++)
- {
- U[i] = D[i] = i;
- L[i + ] = i;
- R[i] = i + ;
- S[i] = ;
- }
- R[m] = ;
- L[] = m;
- sz = m + ;
- }
- void remove(int c)
- {
- //删除一整列
- R[L[c]] = R[c];
- L[R[c]] = L[c];
- //删除行
- for(int i = D[c];i != c;i = D[i])
- {
- for(int j = R[i];j != i;j = R[j])
- {
- D[U[j]] = D[j];
- U[D[j]] = U[j];
- S[X[j]]--;
- }
- }
- }
- void resume(int c)
- {
- //恢复一整列
- L[R[c]] = c;
- R[L[c]] = c;
- //恢复行
- for(int i = U[c];i != c;i = U[i])
- {
- for(int j = L[i];j != i;j = L[j])
- {
- D[U[j]] = j;
- U[D[j]] = j;
- S[X[j]]++;
- }
- }
- }
- void ins(int r,int c)
- {
- S[c]++;
- //纵向插入
- D[U[c]] = sz;
- U[sz] = U[c];
- D[sz] = c;
- U[c] = sz;
- X[sz] = c;
- Y[sz] = r;
- //横向插入
- if(H[r] == -)
- {
- H[r] = L[sz] = R[sz] = sz;
- }
- else
- {
- R[L[H[r]]] = sz;
- L[sz] = L[H[r]];
- R[sz] = H[r];
- L[H[r]] = sz;
- }
- sz++;
- }
- bool dfs(int k)
- {
- if(R[] == )
- {
- return true;
- }
- else
- {
- int m = 0xfffffff,num;
- for(int i = R[];i != ;i = R[i])
- {
- if(S[i] == )
- {
- return false;
- }
- if(m > S[i])
- {
- m = S[i];
- num = i;
- if(m == )
- {
- break;
- }
- }
- }
- remove(num);
- for(int i = D[num];i != num;i = D[i])
- {
- ans[row[Y[i]]][col[Y[i]]] = cont[Y[i]];
- for(int j = R[i];j != i;j = R[j])
- {
- remove(X[j]);
- }
- if(dfs(k + ))
- {
- return true;
- }
- for(int j = L[i];j != i;j = L[j])//恢复顺序改为由左向右居然慢N倍?!
- {
- resume(X[j]);
- }
- }
- resume(num);
- }
- return false;
- }
- int main()
- {
- char input[];
- while(scanf("%s",input),input[] != 'e')
- {
- memset(hashr,false,sizeof(hashr));
- memset(hashc,false,sizeof(hashc));
- memset(hashp,false,sizeof(hashp));
- for(int i = ;i < ;i++)
- {
- for(int j = ;j < ;j++)
- {
- if(input[i * + j] != '.')
- {
- hashr[i][input[i * + j] - ''] = true;
- hashc[j][input[i * + j] - ''] = true;
- hashp[i / * + j / ][input[i * + j] - ''] = true;
- }
- }
- }
- M = * * ;
- N = ;
- init(M);
- for(int i = ;i < ;i++)
- {
- for(int j = ;j < ;j++)
- {
- int k;
- if(input[i * + j] != '.')
- {
- k = input[i * + j] - '';
- }
- else
- {
- k = ;
- }
- if(k != )
- {
- row[N] = i;
- col[N] = j;
- cont[N] = k;
- H[N] = -;
- ins(N,i * + j + );//(i,j)位置已填数字
- ins(N, + i * + k);//i行已有k
- ins(N, + j * + k);//j列已有k
- ins(N++, + (i / * + j / ) * + k);//宫格已有k
- }
- else
- {
- for(k = ;k <= ;k++)
- {
- if(!hashr[i][k] && !hashc[j][k] && !hashp[i / * + j / ][k])
- {
- row[N] = i;
- col[N] = j;
- cont[N] = k;
- H[N] = -;
- ins(N,i * + j + );//(i,j)位置已填数字
- ins(N, + i * + k);//i行已有k
- ins(N, + j * + k);//j列已有k
- ins(N++, + (i / * + j / ) * + k);//宫格已有k
- }
- }
- }
- }
- }
- dfs();
- for(int i = ;i < ;i++)
- {
- for(int j = ;j < ;j++)
- {
- printf("%d",ans[i][j]);
- }
- }
- printf("\n");
- }
- return ;
- }
poj 3074的更多相关文章
- POJ 3074 Sudoku (DLX)
Sudoku Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Statu ...
- 搜索(DLX): POJ 3074 3076 Sudoku
POJ 3074 : Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller ...
- POJ 3074 Sudoku (Dancing Links)
传送门:http://poj.org/problem?id=3074 DLX 数独的9*9的模板题. 具体建模详见下面这篇论文.其中9*9的数独怎么转化到精确覆盖问题,以及相关矩阵行列的定义都在下文中 ...
- 【POJ 3074】 Sudoku
[题目链接] http://poj.org/problem?id=3074 [算法] 将数独问题转化为精确覆盖问题,用Dancing Links求解 转化方法如下 : 我们知道,在一个数独中 : 1. ...
- DLX (poj 3074)
题目:Sudoku 匪夷所思的方法,匪夷所思的速度!!! https://github.com/ttlast/ACM/blob/master/Dancing%20Link%20DLX/poj%2030 ...
- POJ 3074 Sudoku DLX精确覆盖
DLX精确覆盖.....模版题 Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8336 Accepted: ...
- POJ 3074 Sudoku (Dacing Links)
推荐一个写数独很好的博客:http://www.cnblogs.com/grenet/p/3163550.html 主要是把九宫格里的元素换到矩阵里面再求解dancing links 网上找的一模版 ...
- poj 3074 Sudoku(Dancing Links)
Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8152 Accepted: 2862 Descriptio ...
- (简单) POJ 3074 Sudoku, DLX+精确覆盖。
Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgr ...
- POJ 3074 Sudoku(算竞进阶习题)
二进制优化+dfs 话说这题数据中真的丧心病狂..不加inline还过不去.. 因为不会DLX只好用二进制来优化了...万万没想到还是低空飘过 我们在行.列.格分别用一个9位二进制常数来记录什么数能放 ...
随机推荐
- mysql之distinct
记录一下这几天看mysql必知必会的小知识点: 关于mysql查询不同的行 比如记录表中 查询有多少个城市 可能查出很多城市 可以用distinct 来解决这个问题 SELECT DISTINCT c ...
- May Challenge 2019 Division 2 水题讲解
Reduce to One 这题其实蛮水的? 题意就是说: 给定一个 1~n 的序列,每次挑两个数 x y 合并,合并值为 \(x+y+xy\) ,然后求不断合并最后剩下的一个的最大值 随便搞搞发现答 ...
- video 能播放声音不能播放视频,黑屏
与视频编码格式有关,mp4的视频编码有三种:MPEG4(DivX),MPEG4(Xvid),AVC(H264). 浏览器播放视频的支持有限,MP4格式的视频只支持h.264的视频: 视频编码: AVC ...
- [Usaco2018 Open]Talent Show
Description FarmerJohn要带着他的N头奶牛,方便起见编号为1-N,到农业展览会上去,参加每年的达牛秀!他的第i头奶牛重量为wi,才艺水平为ti,两者都是整数.在到达时,Farmer ...
- Light 1289 - LCM from 1 to n (位图标记+素数筛选)
题目链接: http://www.lightoj.com/volume_showproblem.php?problem=1289 题目描述: 给出一个n,求出lcm(1,2,3......n)为多少? ...
- Android 性能优化(23)*性能工具之「Heap Viewer, Memory Monitor, Allocation Tracker」Memory Profilers
Memory Profilers In this document Memory Monitor Heap Viewer Allocation Tracker You should also read ...
- pyCharm最新激活码(2018)
1.修改hosts文件: 添加下面一行到hosts文件,目的是屏蔽掉Pycharm对激活码的验证 0.0.0.0 account.jetbrains.com windwos系统hosts文件路径为:C ...
- CSS动画持续汇总中
一:向上的动态箭头------------------http://www.5599.com/88lz/up_direct.html
- 喜欢Swift编程语言的人主要是初学者?
一早一起来,朋友圈除了被苹果发布会刷屏外,还漫天散布着一条类似的招聘消息:“招聘iOS程序员,要求拥有5年的Swift开发经验,有狼性,待遇月薪20K+,专车接送.” 随后身边的朋友很快就开始调侃:& ...
- PHP安装yaf在ubuntu下面的问题解决
1.在执行make的时候出现如下错误: In file included from /root/yaf-2.1.2/yaf_router.c:28: /usr/include/php/ext/pcre ...