2019独角兽企业重金招聘Python工程师标准>>>

dlx算法解数独,有空会写详解,暂时就这样了

Sudoku
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 7697 Accepted: 2731

Description

In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,

. 2 7 3 8 . . 1 .
. 1 . . . 6 7 3 5
. . . . . . . 2 9
3 . 5 6 9 2 . 8 .
. . . . . . . . .
. 6 . 1 7 4 5 . 3
6 4 . . . . . . .
9 5 1 8 . . . 7 .
. 8 . . 6 5 3 4 .

Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.

Input

The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.

Output

For each test case, print a line representing the completed Sudoku puzzle.

Sample Input

.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.
end

Sample Output

527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936

Source

Stanford Local 2006

[Submit]   [Go Back]   [Status]   [Discuss]

/*=============================================================================
#     FileName: 3074.cpp
#         Desc:
#       Author: zhuting
#        Email: cnjs.zhuting@gmail.com
#     HomePage: my.oschina.net/locusxt
#      Version: 0.0.1
#    CreatTime: 2014-01-16 21:44:18
#   LastChange: 2014-01-16 21:44:18
#      History:
=============================================================================*/
/** 数独需要满足的四个条件:* 1.每个格子都有数字* 2.每一行要有1-9* 3.每一列要有1-9* 4.每个3*3的块要有1-9** 1-81列 表示某个格子有没有填数字,填了则为1* 82-162列 表示某一行有没有1-9* 163-243列 表示某一列有没有1-9* 244-324列 表示某个块有没有1-9** 共9*9*9行* 表示某一个格子填了某个数后的影响*/#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <algorithm>
#define maxl 100
#define maxc 325 //最大列数,包含头结点
#define maxr 730 //最大行数,包含待匹配行
#define maxn 240000 //最大总结点数
#define head 0 //head的编号为0
#define GET_CEL(i, j, k) i*9+j
#define GET_ROW(i, j, k) 80+i*9+k
#define GET_COL(i, j, k) 161+j*9+k
#define GET_BLO(i, j, k) 242+(3*(i/3)+j/3)*9+k
#define GET_I(l) (l-1)/81
#define GET_J(l) (l-1)%81/9
#define GET_K(l) (l-1)%81%9+1const int m = 729;//行数
const int n = 324;//列数
bool mymap[maxr][maxc];int num[maxc] = {0};//数组实现的dancing links
int up[maxn] = {0}, down[maxn] = {0}, left[maxn] = {0}, right[maxn] = {0};//顾名思义是某个结点的上下左右结点的标号
int column[maxn] = {0}, row[maxn] = {0}, ans[maxn] = {0};//某个结点对应的行号,ans是取的行号的数组char str[maxl];/** 每填一个数,假设填在数独i行j列填的是k* 那么会产生以下影响:* 9*j+i个cell被填上了数字*///生成初始的01串
void gen_zero_one()
{int cur_line = 0;for (int i = 0; i < 9; ++i){for (int j = 0; j < 9; ++j){for (int k = 1; k <= 9; ++k){mymap[cur_line][GET_CEL(i, j, k)] = 1;mymap[cur_line][GET_ROW(i, j, k)] = 1;mymap[cur_line][GET_COL(i, j, k)] = 1;mymap[cur_line][GET_BLO(i, j, k)] = 1;++cur_line;}}}return;
}//生产初始的节点表
void gen_node()
{int id = 1;int tmp = 0;int lineup[maxc] = {0};for (int j = 0; j < n; ++j)//待匹配行{lineup[j] = id;column[id] = j + 1;if (j != n - 1){right[id] = id + 1;}left[id] = id - 1;++id;}right[head] = 1;left[head] = id - 1;right[id - 1] = head;for (int i = 0; i < m; ++i){int first_id = 0;int left_id = 0;for (int j = 0; j < n; ++j){//scanf("%d", &tmp);tmp = mymap[i][j];if (tmp){row[id] = i + 1;column[id] = j + 1;if (first_id == 0){first_id = id;left_id = id;}else{left[id] = left_id;right[left_id] = id;left_id = id;}int upid = lineup[j];up[id] = upid;down[upid] = id;lineup[j] = id;++id;}}if (first_id != 0){left[first_id] = left_id;right[left_id] = first_id;}}for (int j = 0; j < n; ++j){down[lineup[j]] = j + 1;up[j + 1] = lineup[j];}//test(id);return;
}void init()//初始化
{memset(up, 0, sizeof(up));memset(down, 0, sizeof(down));memset(left, 0, sizeof(left));memset(right, 0, sizeof(right));memset(column, 0, sizeof(column));memset(row, 0, sizeof(row));memset(ans, 0, sizeof(ans));memset(mymap, 0, sizeof(mymap));for (int i = 1; i <= n; ++i)num[i] = 9;return;
}//这里的remove其实并没有真正删除掉结点,可以用resume恢复
void remove(int c)//去掉c号结点,以及在c所在列上有结点的行的结点
{left[right[c]] = left[c];right[left[c]] = right[c];for (int i = down[c]; i != c; i = down[i]){for (int j = right[i]; j != i; j = right[j]){up[down[j]] = up[j];down[up[j]] = down[j];--num[column[j]];}}return;
}void resume(int c)//remove的逆操作
{left[right[c]] = c;right[left[c]] = c;for (int i = up[c]; i != c; i = up[i]){for (int j = right[i]; j != i; j = right[j]){up[down[j]] = j;down[up[j]] = j;++num[column[j]];}}return;
}void recover(int t)
{for (int i = 0; i < t; ++i){int tmp = ans[i];int cur = GET_I(tmp) * 9 + GET_J(tmp);str[cur] = GET_K(tmp) + '0';/*printf("%d:\n", tmp);printf("%d %d %d\n", GET_I(tmp), GET_J(tmp), GET_K(tmp));*/}return;
}//我们的终极目标实际上是把十字链表中所有的结点都删掉,只留一个头结点
bool dance(int k)//这里的k实际上是没多大意义的
{//printf("dance: %d\n", k);int c = right[head];//c是头结点的右边一个结点if (c == head)//只剩下十字链表的头结点,则完成了目标{recover(k);return true;}int min_n = num[c];int min_cur = c;while(true){c = right[c];if (c == head)break;if(num[c] < min_n){min_n = num[c];min_cur = c;}}c = min_cur;remove(c);for (int i = down[c]; i != c; i = down[i])//这里其实是枚举某一行对待匹配行的第c位进行匹配{ans[k] = row[i];for (int j = right[i]; j != i; j = right[j])remove(column[j]);//remove待匹配行的column[j]结点if (dance(k + 1))return true;for (int j = left[i]; j != i; j = left[j])resume(column[j]);}resume(c);return false;
}void parse(char* a)
{int tmp = 0;for(int i = 0; i < 9; ++i){for (int j = 0; j < 9; ++j){if(a[i * 9 + j] != '.'){tmp = a[i * 9 + j] - '0';remove(GET_CEL(i, j, tmp) + 1);remove(GET_ROW(i, j, tmp) + 1);remove(GET_COL(i, j, tmp) + 1);remove(GET_BLO(i, j, tmp) + 1);}}}return;
}int main()
{while (true){scanf("%s", str);if (str[0] == 'e'){break;}init();gen_zero_one();gen_node();parse(str);int is_possible = dance(0);if (is_possible){printf("%s\n", str);}elseprintf("error\n");}return 0;
}

转载于:https://my.oschina.net/locusxt/blog/193922

poj 3074 Sudoku相关推荐

  1. POJ - 3074 Sudoku(DLX)

    题目链接:点击查看 题目大意:用更快的方法解数独 题目分析:这个题和上一个题都是解数独,但时间限制少了一秒钟,难度却上升了一个档次,上一个题用暴力dfs完全可以跑出来,不过要用1.5秒左右的时间,所以 ...

  2. POJ 2676 Sudoku【DancingLinks,数独】

    http://poj.org/problem?id=2676 POJ 2676 Sudoku 也是求解规模为9*9的数独问题,与POJ 3074 Sudoku相同的问题,只是修改了输入输出格式而已.. ...

  3. Poj 2676 Sudoku[dfs]

    题目大意: 九宫格问题,也有人叫数独问题 把一个9行9列的网格,再细分为9个3*3的子网格,要求每行.每列.每个子网格内都只能使用一次1~9中的一个数字,即每行.每列.每个子网格内都不允许出现相同的数 ...

  4. POJ 2676 Sudoku 数独

    点击打开链接 Sudoku Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 12360   Accepted: 6168   ...

  5. POJ - 2676 Sudoku(dfs)

    题目链接:点击查看 题目大意:解数独,具体规则是,在一个9*9的区域内填充1~9的数字,要求: 每列不许有重复数字 每行不许有重复数字 每个3*3的九宫格内不许有重复数字 题目分析:因为至多只有81个 ...

  6. POJ 2676 Sudoku (数独求解器 DFS)

    题目链接 POJ2676 题目大意 输入n个数独,空格用0表示,填数独(符合的一种方案即可). 分析 类似于八皇后的简单搜索题,用DFS回溯法求解. 将空格的位置都记录下来,1个1个填下去,填不下去就 ...

  7. POJ - 3074 DancingLink 数独 九宫格

    ---------------- 原代码链接:https://blog.csdn.net/guagua_de_xiaohai/article/details/88921307 ------------ ...

  8. ACM练级日志:POJ 3074 数独与DLX

    各位还在使用百度空间的同学们,请原谅最近被我刷屏-- 数独是DLX建模的最经典应用,它最好地示范了"行=决策,列=约束"的建模方法,配合快速的DLX深搜,使它成为了目前最快的求解数 ...

  9. kuangbin带你飞专题合集

    题目列表 [kuangbin带你飞]专题一 简单搜索 [kuangbin带你飞]专题二 搜索进阶 [kuangbin带你飞]专题三 Dancing Links [kuangbin带你飞]专题四 最短路 ...

  10. ACM题集以及各种总结大全(转)

    ACM题集以及各种总结大全! 虽然退役了,但是整理一下,供小弟小妹们以后切题方便一些,但由于近来考试太多,顾退役总结延迟一段时间再写!先写一下各种分类和题集,欢迎各位大牛路过指正. 一.ACM入门 关 ...

最新文章

  1. 抽象语法树 Abstract syntax tree
  2. decimal(C# 参考)
  3. SecureCRT设置和Xshell一样的快速命令集(使用快捷键输入命令和密码)
  4. error C1004 发现意外的文件尾
  5. ClewareControl 2.4 发布,传感器控制程序
  6. linux终端Tab提示对大小写不敏感
  7. 带学生参加电赛,5个国一,2个国二!15个省奖!
  8. nc 结合htc hts 反弹shell(内网代理环境下)
  9. desktop docker 无法卸载_在docker-for-desktop OSX上删除kubernetes集群
  10. 【多任务】如何利用多任务学习提升模型性能?
  11. Atitit file cms api jcr1 jcr2 目录 1.1. 么是JSR-170幸运的是,被称为Java内容仓库(Java Content Repository,JCR)的JSR-
  12. -f linux_SAIL-F-8-2-4-0-12流量积算仪-老友网
  13. Android全局修改字体大小,Android 应用全局字体调节或禁止随系统字体大小更改
  14. 分享一个超级好用的在线生成地图SiteMap制作工具
  15. 计算机操作员中级操作技能,计算机操作员中级操作技能试卷.doc
  16. 1-65535字符集
  17. 完全但不完美信息博弈
  18. STM32F107VCTx HAL库 USART通信 DMA通信 友善串口调试助手 PL2303驱动安装
  19. 主语从句、宾语从句、表语从句、同位语从句
  20. 双系统linux哪种好,双系统安装实战,这个Linux系统超级简单

热门文章

  1. js便签笔记(5)——Dean Edwards大牛的跨浏览器AddEvent()设计(不知道是不是jQuery事件系统的原型)...
  2. [Python]关键字is和操作符==
  3. httpHandler实现.Net无后缀名Web访问
  4. 涂鸦板制作教程——其中的重做和撤消我觉得不错
  5. 在Windos上安装Nginx
  6. O(N)求出1~n逆元
  7. oracle存储过程中返回一个程序集
  8. 笔记:Java 性能优化权威指南 第5章 Java 应用性能分析
  9. mahout推荐15-在hadoop上运行MapReduce
  10. 再看中国互联网web2.0百强名单