zoukankan      html  css  js  c++  java
  • POJ3074 Sudoku

    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(0),f(1); char ch;
     12     while(!isdigit(ch=getchar())) if(ch=='-') f=-1;
     13     while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
     14     return f*x;
     15 }
     16 int id[10][10];//打表算出i,j所在的九宫格 
     17 inline void pre_work()
     18 {
     19     for(res i=0 ; i<3 ; i++)
     20     {
     21         for(res j=0 ; j<3 ; j++) id[i][j]=0;
     22         for(res j=3 ; j<6 ; j++) id[i][j]=3;
     23         for(res j=6 ; j<9 ; j++) id[i][j]=6;    
     24     } 
     25     for(res i=3 ; i<6 ; i++)
     26     {
     27         for(res j=0 ; j<3 ; j++) id[i][j]=1;
     28         for(res j=3 ; j<6 ; j++) id[i][j]=4;
     29         for(res j=6 ; j<9 ; j++) id[i][j]=7;    
     30     } 
     31     for(res i=6 ; i<9 ; i++)
     32     {
     33         for(res j=0 ; j<3 ; j++) id[i][j]=2;
     34         for(res j=3 ; j<6 ; j++) id[i][j]=5;
     35         for(res j=6 ; j<9 ; j++) id[i][j]=8;    
     36     }         
     37 }
     38 
     39 char str[10][10];
     40 int row[9],col[9],grid[9],cnt[512],num[512],tot;    
     41 
     42 inline void flip(int x,int y,int z) 
     43 {
     44     row[x]^=1<<z;    col[y]^=1<<z;
     45     grid[id[x][y]]^=1<<z;
     46 }
     47 
     48 bool dfs(int now)
     49 {
     50     if(!now) return 1;
     51     int tmp=10,x,y;
     52     //找最好算的位置
     53     for(res i=0 ; i<9 ; i++)
     54         for(res j=0 ; j<9 ; 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]='1'+z; //注意是1
     67         flip(x,y,z);
     68         if(dfs(now-1)) 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=0 ; i<1<<9 ; i++)
     80         for(res j=i ; j ; j-=j&-j) cnt[i]++;
     81     for(res i=0 ; i<9 ; i++) num[1<<i]=i;
     82     char s[100];
     83     while(~scanf("%s",s) && s[0]!='e')
     84     {
     85         for(res i=0 ; i<9 ; i++)
     86             for(res j=0 ; j<9 ; j++) str[i][j]=s[i*9+j];
     87         for(res i=0 ; i<9 ; i++) row[i]=col[i]=grid[i]=(1<<9)-1;
     88         tot=0;
     89         for(res i=0 ; i<9 ; i++)
     90             for(res j=0 ; j<9 ; j++) 
     91                 if(str[i][j]!='.') flip(i,j,str[i][j]-'1');//注意这里是-1,因为是0~8    
     92                 else tot++;
     93         dfs(tot);
     94         for(res i=0 ; i<9 ; i++)
     95             for(res j=0 ; j<9 ; j++) s[i*9+j]=str[i][j];
     96         puts(s);
     97     }   
     98     
     99     return 0;
    100 }
    View Code
  • 相关阅读:
    hdu 3786 寻找直系亲属
    about the plan
    2013 ACM/ICPC Asia Regional Online —— Warmup1 1005 Balls Rearrangement
    poj 1833 给poj跪了 字典排序
    20170630总结
    20170701总结
    20170628总结
    20170629总结
    20170626总结
    20170627总结
  • 原文地址:https://www.cnblogs.com/wmq12138/p/10368693.html
Copyright © 2011-2022 走看看