POJ 2676 Sudoku

题目链接:http://poj.org/problem?id=2676

数独问题。用dancing links解决。

建图参考 http://wenku.baidu.com/link?url=3Tk5gVYew3mSQ2f2LxDODxPg3v-yqJPUaEkuZpfkHTxfSPQuM_n8TGl2Swp68XQY9MYN2BENZ-pmv9dpoh3Ulqt1lT-ZNo90jcJyi1eXasm

要注意的就是搜索的时候 要先搜索 那一列中节点最少的,否则时间会很长。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <string>
  5 #include <iomanip>
  6 using namespace std;
  7 int T;
  8 #define maxn 9*9*9*4+81*4+10
  9 int L[maxn], R[maxn], D[maxn], U[maxn];
 10 int H[maxn], C[maxn], ans[85], sum[81*4+10];
 11 int mp[10][10];
 12 int head, cnt;
 13 struct Node{
 14     int x, y, val;
 15 }hmap[9*9*9+10];
 16 void addnode(int x, int y, int val, int h){
 17     int pos1 = 81*0 + (x-1)*9+y;
 18     int pos2 = 81*1 + (x-1)*9 + val;
 19     int pos3 = 81*2 + (y-1)*9 + val;
 20     int pos4 = 81*3 + (((x-1)/3)*3 + (y-1)/3)*9 + val;
 21
 22     H[cnt+1] = H[cnt+2] = H[cnt+3] = H[cnt+4] = h;
 23     C[cnt+1] = pos1; C[cnt+2] = pos2; C[cnt+3] = pos3; C[cnt+4] = pos4;
 24
 25     R[cnt+1] = cnt+2; R[cnt+2] = cnt+3; R[cnt+3] = cnt+4; R[cnt+4] = cnt+1;
 26     L[cnt+1] = cnt+4; L[cnt+2] = cnt+1; L[cnt+3] = cnt+2; L[cnt+4] = cnt+3;
 27
 28     D[U[pos1]] = cnt+1; D[cnt+1] = pos1;  U[cnt+1] = U[pos1]; U[pos1] = cnt+1;
 29     D[U[pos2]] = cnt+2; D[cnt+2] = pos2;  U[cnt+2] = U[pos2]; U[pos2] = cnt+2;
 30     D[U[pos3]] = cnt+3; D[cnt+3] = pos3;  U[cnt+3] = U[pos3]; U[pos3] = cnt+3;
 31     D[U[pos4]] = cnt+4; D[cnt+4] = pos4;  U[cnt+4] = U[pos4]; U[pos4] = cnt+4;
 32
 33     sum[pos1]++; sum[pos2]++; sum[pos3]++; sum[pos4]++;
 34     cnt+=4;
 35
 36     hmap[h].x = x; hmap[h].y = y; hmap[h].val = val;
 37 }
 38 void init(){
 39     memset(sum, 0, sizeof(sum));
 40     head = 0; cnt = 0;
 41     R[head] = 1; L[head] = 81*4;
 42     U[head] = head; D[head] = head;
 43     for(int i = 1; i <= 81*4; i++){  //头节点。
 44         cnt++;
 45         H[cnt] = 0; C[cnt] = i;
 46         U[cnt] = cnt; D[cnt] = cnt;
 47         if(i == 81*4){
 48             R[cnt-1] = cnt; L[cnt] = cnt-1;
 49             R[cnt] = head;
 50         }
 51         else{
 52             R[cnt-1] = cnt; L[cnt] = cnt-1;
 53         }
 54     }
 55     int h = 0;
 56     for(int i = 1; i <= 9; i++){
 57         string temp; cin>>temp;
 58         for(int j = 0; j < 9; j++){
 59             if(temp[j] == ‘0‘){
 60                 for(int k = 1; k <= 9; k++) addnode(i, j+1, k, ++h);
 61             }
 62             else{
 63                 addnode(i, j+1, int(temp[j]-‘0‘), ++h);
 64             }
 65         }
 66     }
 67 }
 68 void remove(int c){
 69     R[L[c]] = R[c]; L[R[c]] = L[c];
 70     for(int i = D[c]; i != c; i = D[i]){
 71         for(int j = R[i]; j != i; j = R[j]){
 72             U[D[j]] = U[j]; D[U[j]] = D[j];
 73             sum[C[j]]--;
 74         }
 75     }
 76 }
 77 void resume(int c){
 78     R[L[c]] = c;
 79     L[R[c]] = c;
 80     for(int i = D[c]; i != c; i = D[i]){
 81         for(int j = R[i]; j != i; j = R[j]){
 82             U[D[j]] = j;
 83             D[U[j]] = j;
 84             sum[C[j]]++;
 85         }
 86     }
 87 }
 88 bool dance(int k){
 89     int c = R[head];
 90     if(c == head){
 91         return true;
 92     }
 93     int min = 99999;
 94     for(int i = R[head];i != head; i = R[i]){
 95         if(sum[i]<=min){
 96             min = sum[i];
 97             c = i;
 98         }
 99     }
100     remove(c);
101     for(int i = D[c]; i != c; i = D[i]){
102         ans[k] = H[i];
103         for(int j = R[i]; j != i; j = R[j]) remove(C[j]);
104         if(dance(k+1)) return true;
105         for(int j = R[i]; j != i; j = R[j]) resume(C[j]);
106     }
107     resume(c);
108     return false;
109 }
110 int main(){
111     scanf("%d", &T);
112     while(T--){
113         init();
114         bool flag = dance(0);
115         for(int i = 0; i < 81; i++){
116             mp[hmap[ans[i]].x][hmap[ans[i]].y] = hmap[ans[i]].val;
117         }
118         for(int i = 1; i <= 9; i++){
119             for(int j = 1; j <= 9; j++){
120                 printf("%d", mp[i][j]);
121             }
122             printf("\n");
123         }
124     }
125     return 0;
126 }
时间: 2024-08-07 18:37:46

POJ 2676 Sudoku的相关文章

POJ 2676 Sudoku (数独)

经典搜索问题,主要是时间上的优化,我用了三个辅助数组记录信息 row[i][k] = 1表示第i行数字k已经被使用,col[j][k] = 1表第j列数字k已经被使用,blo[i][k]表示第i个小九宫格中数字k已经被使用 还有很重要的一个优化(没有优化的话可能会超时,或者非常慢,像POJ讨论区里有很多说正着搜超时,倒着搜0ms,这的确是一个可以用的方法,但是有一定的随机性),每次填数字时,先扫描一遍整个矩阵,找出可选数字情况最少的那个0所在的地方,优先填这里,这样会使得搜索树尽可能的"瘦&qu

ACM : POJ 2676 SudoKu DFS - 数独

SudoKu Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu POJ 2676 Description Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure. In some of the c

poj 2676 Sudoku (dfs)

链接:poj 2676 题意:给定一个未完成的数独,0是待填位置,其他均为已填入的数字.如果能将其 补充完整,则输出补充完整的数独(有多组答案输出任意一组),否则原样输出 数独:一个9行9列的网格,包括9个3*3的子网格,要求每行.每列.每个子网格内 都只能使用一次1-9中的一个数字, 即每行.每列.每个子网格内都不允许出现相同的数字. 分析:对于每一个未填的格,依次判断它所在行.列.子网格是否填了1-9, 若都未填,先填上该值,继续搜索, 若无法填写了,再回溯,填上其他可能的值,继续搜索 看别

POJ 2676 Sudoku (搜索,Dancing Links)

题目: http://poj.org/problem?id=2676 题意: 数独,每行1-9,每列1-9,每3*3小格1-9,填数,不能重复 方法:Dancing Links(16ms)或者DFS暴搜(400-900ms) Dancing Links(DLX) 是为了解决矩阵精确覆盖问题的算法,算法效率非常高 使用DLX解决的问题必须转化为矩阵精确覆盖问题: 1.DLX详解: http://wenku.baidu.com/view/d8f13dc45fbfc77da269b126.html 2

poj 2676 Sudoku (基础DFS)

Sudoku Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15456   Accepted: 7574   Special Judge Description Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure.

POJ 2676 Sudoku (数独 DFS)

Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14368   Accepted: 7102   Special Judge Description Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure. In some

搜索 --- 数独求解 POJ 2676 Sudoku

Sudoku Problem's Link:   http://poj.org/problem?id=2676 Mean: 略 analyse: 记录所有空位置,判断当前空位置是否可以填某个数,然后直接DFS,注意从后往前搜索,时间比正向搜快很多.16ms水过 Time complexity: O(n) Source code:  // Memory Time // 1347K 0MS // by : crazyacking // 2015-04-10-14.30 #include<map>

POJ 2676 - Sudoku(数独)

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2676 题目大意: 给出一个数字n,表示有n组数据. 每组数据包括一个n*n的数独,0表示未填的数字.数字之间没有空格. 输出填好的数独,使得每行.每列.每个九宫格中的数字都不重复. 分析: 经典搜索题目. 数组一定要开大一点,数组一定要开大一点,数组一定要开大一点. AC代码: 1 #include<cstdio> 2 #include<algorith

Poj 2676 Sudoku[dfs]

题目大意: 九宫格问题,也有人叫数独问题 把一个9行9列的网格,再细分为9个3*3的子网格,要求每行.每列.每个子网格内都只能使用一次1~9中的一个数字,即每行.每列.每个子网格内都不允许出现相同的数字. 0是待填位置,其他均为已填入的数字. 要求填完九宫格并输出(如果有多种结果,则只需输出其中一种) 如果给定的九宫格无法按要求填出来,则输出原来所输入的未填的九宫格 思路: DFS 深搜 char map[10][10];/*数据存储*/bool row[10][10];/*行存在数*/bool