POJ 2676 Sudoku

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

数独问题。用dancing links解决。

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

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

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <iomanip>
using namespace std;
int T;
#define maxn 9*9*9*4+81*4+10
int L[maxn], R[maxn], D[maxn], U[maxn];
int H[maxn], C[maxn], ans[85], sum[81*4+10];
int mp[10][10];
int head, cnt;
struct Node{
    int x, y, val;
}hmap[9*9*9+10];
void addnode(int x, int y, int val, int h){
    int pos1 = 81*0 + (x-1)*9+y;
    int pos2 = 81*1 + (x-1)*9 + val;
    int pos3 = 81*2 + (y-1)*9 + val;
    int pos4 = 81*3 + (((x-1)/3)*3 + (y-1)/3)*9 + val;
    
    H[cnt+1] = H[cnt+2] = H[cnt+3] = H[cnt+4] = h;
    C[cnt+1] = pos1; C[cnt+2] = pos2; C[cnt+3] = pos3; C[cnt+4] = pos4;
    
    R[cnt+1] = cnt+2; R[cnt+2] = cnt+3; R[cnt+3] = cnt+4; R[cnt+4] = cnt+1;
    L[cnt+1] = cnt+4; L[cnt+2] = cnt+1; L[cnt+3] = cnt+2; L[cnt+4] = cnt+3;
    
    D[U[pos1]] = cnt+1; D[cnt+1] = pos1;  U[cnt+1] = U[pos1]; U[pos1] = cnt+1;
    D[U[pos2]] = cnt+2; D[cnt+2] = pos2;  U[cnt+2] = U[pos2]; U[pos2] = cnt+2;
    D[U[pos3]] = cnt+3; D[cnt+3] = pos3;  U[cnt+3] = U[pos3]; U[pos3] = cnt+3;
    D[U[pos4]] = cnt+4; D[cnt+4] = pos4;  U[cnt+4] = U[pos4]; U[pos4] = cnt+4;
    
    sum[pos1]++; sum[pos2]++; sum[pos3]++; sum[pos4]++;
    cnt+=4;
    
    hmap[h].x = x; hmap[h].y = y; hmap[h].val = val;
}
void init(){
    memset(sum, 0, sizeof(sum));
    head = 0; cnt = 0;
    R[head] = 1; L[head] = 81*4;
    U[head] = head; D[head] = head;
    for(int i = 1; i <= 81*4; i++){  //头节点。 
        cnt++;
        H[cnt] = 0; C[cnt] = i;
        U[cnt] = cnt; D[cnt] = cnt;
        if(i == 81*4){
            R[cnt-1] = cnt; L[cnt] = cnt-1;
            R[cnt] = head;
        }
        else{
            R[cnt-1] = cnt; L[cnt] = cnt-1;
        }
    }
    int h = 0;
    for(int i = 1; i <= 9; i++){
        string temp; cin>>temp;
        for(int j = 0; j < 9; j++){
            if(temp[j] == '0'){
                for(int k = 1; k <= 9; k++) addnode(i, j+1, k, ++h);
            }
            else{
                addnode(i, j+1, int(temp[j]-'0'), ++h);
            }
        }
    }
}
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]){
            U[D[j]] = U[j]; D[U[j]] = D[j];
            sum[C[j]]--;
        }
    }
}
void resume(int c){
    R[L[c]] = c;
    L[R[c]] = c;
    for(int i = D[c]; i != c; i = D[i]){
        for(int j = R[i]; j != i; j = R[j]){
            U[D[j]] = j;
            D[U[j]] = j;
            sum[C[j]]++;
        }
    }
}
bool dance(int k){
    int c = R[head];
    if(c == head){
        return true;
    }
    int min = 99999;
    for(int i = R[head];i != head; i = R[i]){
        if(sum[i]<=min){
            min = sum[i];
            c = i;
        }
    }
    remove(c);
    for(int i = D[c]; i != c; i = D[i]){
        ans[k] = H[i];
        for(int j = R[i]; j != i; j = R[j]) remove(C[j]);
        if(dance(k+1)) return true;
        for(int j = L[i]; j != i; j = L[j]) resume(C[j]);
    } 
    resume(c);
    return false;    
}
int main(){
    scanf("%d", &T);
    while(T--){
        init();    
        bool flag = dance(0);        
        for(int i = 0; i < 81; i++){
            mp[hmap[ans[i]].x][hmap[ans[i]].y] = hmap[ans[i]].val;
        }
        for(int i = 1; i <= 9; i++){
            for(int j = 1; j <= 9; j++){
                printf("%d", mp[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}

 

posted @ 2015-04-23 22:44  下周LGD该赢了吧  阅读(132)  评论(0编辑  收藏  举报