POJ3074 Sudoku

  • 与POJ2676相比,这一题搜索时每一步都找到最好确定的点进行枚举
  • 对于每行、每列、每个九宫格,都分别用一个9位二进制数保存还有那些数还可以填
  • 对于每个位置,将其所在行、列、九宫格所对应的二进制数进行或运算即可得到该位置能填哪些数,用lowbit运算(取出最低的为1的数位)即可吧能填的数字取出。
  • 其他见代码
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <queue>
  4. #include <algorithm>
  5. #include <iostream>
  6. #include <cctype>
  7. using namespace std;
  8.  
  9. #define res register int
  10. inline int read() {
  11. int x(),f(); char ch;
  12. while(!isdigit(ch=getchar())) if(ch=='-') f=-;
  13. while(isdigit(ch)) x=x*+ch-'',ch=getchar();
  14. return f*x;
  15. }
  16. int id[][];//打表算出i,j所在的九宫格
  17. inline void pre_work()
  18. {
  19. for(res i= ; i< ; i++)
  20. {
  21. for(res j= ; j< ; j++) id[i][j]=;
  22. for(res j= ; j< ; j++) id[i][j]=;
  23. for(res j= ; j< ; j++) id[i][j]=;
  24. }
  25. for(res i= ; i< ; i++)
  26. {
  27. for(res j= ; j< ; j++) id[i][j]=;
  28. for(res j= ; j< ; j++) id[i][j]=;
  29. for(res j= ; j< ; j++) id[i][j]=;
  30. }
  31. for(res i= ; i< ; i++)
  32. {
  33. for(res j= ; j< ; j++) id[i][j]=;
  34. for(res j= ; j< ; j++) id[i][j]=;
  35. for(res j= ; j< ; j++) id[i][j]=;
  36. }
  37. }
  38.  
  39. char str[][];
  40. int row[],col[],grid[],cnt[],num[],tot;
  41.  
  42. inline void flip(int x,int y,int z)
  43. {
  44. row[x]^=<<z; col[y]^=<<z;
  45. grid[id[x][y]]^=<<z;
  46. }
  47.  
  48. bool dfs(int now)
  49. {
  50. if(!now) return ;
  51. int tmp=,x,y;
  52. //找最好算的位置
  53. for(res i= ; i< ; i++)
  54. for(res j= ; j< ; j++)
  55. {
  56. if(str[i][j]!='.') continue;
  57. int val=row[i]&col[j]&grid[id[i][j]];//不能确定的数的个数
  58. if(cnt[val]<tmp) {
  59. tmp=cnt[val],x=i,y=j;
  60. }
  61. }
  62. int val=row[x]&col[y]&grid[id[x][y]];
  63. for(;val;val-=val&-val)
  64. {
  65. int z=num[val&-val];//要填的数
  66. str[x][y]=''+z; //注意是1
  67. flip(x,y,z);
  68. if(dfs(now-)) return true;
  69. flip(x,y,z);
  70. str[x][y]='.';
  71. }
  72. return false;
  73. }
  74.  
  75. int main()
  76. {
  77. pre_work();
  78. //为了减少空间,用0~8表示1~9
  79. for(res i= ; i<<< ; i++)
  80. for(res j=i ; j ; j-=j&-j) cnt[i]++;
  81. for(res i= ; i< ; i++) num[<<i]=i;
  82. char s[];
  83. while(~scanf("%s",s) && s[]!='e')
  84. {
  85. for(res i= ; i< ; i++)
  86. for(res j= ; j< ; j++) str[i][j]=s[i*+j];
  87. for(res i= ; i< ; i++) row[i]=col[i]=grid[i]=(<<)-;
  88. tot=;
  89. for(res i= ; i< ; i++)
  90. for(res j= ; j< ; j++)
  91. if(str[i][j]!='.') flip(i,j,str[i][j]-'');//注意这里是-1,因为是0~8
  92. else tot++;
  93. dfs(tot);
  94. for(res i= ; i< ; i++)
  95. for(res j= ; j< ; j++) s[i*+j]=str[i][j];
  96. puts(s);
  97. }
  98.  
  99. return ;
  100. }

POJ3074 Sudoku的更多相关文章

  1. POJ3074 Sudoku(lowbit优化搜索)

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

  2. POJ3074 Sudoku —— Dancing Links 精确覆盖

    题目链接:http://poj.org/problem?id=3074 Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissio ...

  3. POJ3074 Sudoku 舞蹈链 DLX

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求解. 题解 DLX + 矩阵构建  (两个传送门) 代码 #include & ...

  4. POJ3074 Sudoku 剪枝深(神?)搜

    emm...挺秀的...挺神的? 每行,每列,每宫用一个二进制数表示选或没选的状态,刚开始设没选为1,然后更改状态的时候异或一下就好了: 这样可以通过lowbit取出每一个没有选过的数:(妙啊? 关于 ...

  5. [poj3074]Sudoku(舞蹈链)

    题目链接:http://poj.org/problem?id=3074 舞蹈链精确覆盖的经典题目,一个数独每个位置的要求,可以得到以下四个约束1.每个位置有且只有一个数字2.每个位置的数字在一行只能出 ...

  6. 【转】Dancing Links题集

    转自:http://blog.csdn.net/shahdza/article/details/7986037 POJ3740 Easy Finding [精确覆盖基础题]HUST1017 Exact ...

  7. Dancing Links 专题总结

    算法详细:Dancing Links博客 1.精确覆盖: ZOJ3209 Treasure Map HUST1017 Exact cover POJ3074 Sudoku 2.可重复覆盖: HDU22 ...

  8. dancing links 题集转自夏天的风

    POJ3740     Easy Finding [精确覆盖基础题] HUST1017    Exact cover [精确覆盖基础] HDOJ3663 Power Stations [精确覆盖] Z ...

  9. 【POJ3074】Sudoku DLX(Dancing Links)

    数独就要DLX,不然不乐意. 数独的DLX构造:9*9个点每一个点有9种选择,这构成了DLX的729行,每行.列.阵有限制,均为9行(/列/阵),然后每行(/列/阵)都有九种数的情况.于是就有了3*9 ...

随机推荐

  1. 276. Paint Fence篱笆涂色

    [抄题]: There is a fence with n posts, each post can be painted with one of the k colors. You have to ...

  2. java中如何实现两个值互换

    public class SwapVariable { public static void main(String[] args) { // 将两个数据进行交换: method2(,); metho ...

  3. Linux ssldump命令

    一.简介 tcpdump是一款很强大.很有用的网络侦听软件,但是对于ssl加密的数据包就无能为力了:ssldump则是一款可以侦听ssl加密的数据包的软件.   二.安装 1)通过yum安装 yum ...

  4. [c++] polymorphism without virtual function

    polymorphism without virtual function

  5. 常用工具类——StringUtils

    /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreem ...

  6. SQL数据透视

    透视是一种通过聚合和旋转把数据行转换成数据列的技术.当透视数据时,需要确定三个要素:要在行(分组元素)中看到的元素,要在列(扩展元素)上看到的元素,要在数据部分看到的元素(聚合元素). SQL Ser ...

  7. Exception (2) Java Exception Handling

    The Java programming language uses exceptions to handle errors and other exceptional events.An excep ...

  8. g++中宏NULL究竟是什么?

    NULL是个指针,还是个整数?0?或(void*)0?答案是和g++版本有关.g++ 4.6支持C++11,引入了nullptr,也许会发生变化. 可以写段简单代码求证一下: #include < ...

  9. JavaScript中两种类型的全局对象/函数【转】

    Snandy Stop, thinking is the essence of progress. JavaScript中两种类型的全局对象/函数 这里所说的JavaScript指浏览器环境中的包括宿 ...

  10. vcenter安装错误The DSN is pointing to anunspported ODBC driver...

    在安装vcenter server中采用现有独立sql server数据库时出现下列错误. 这是由于当前独立数据库版本和当前系统的客户端驱动不匹配.导致我们在odbc中配置dsn无法正常运行. 如sq ...