poj 3074 Sudoku

        求一个9*9的数独的解,保证有唯一解。DLX模版题,做题的时候,我发现回溯时如果不是和搜的过程刚好逆回去的话,效率会降低不少,但这不影响正确性,不知道为什么。。。


#include <stdlib.h>  
#include <iostream>  
#include <stdio.h>  
#include <string.h>  
#include <vector>  
using namespace std;     
    
#define ll long long    
  
const int SLOT = 0;  
const int ROW = 1;  
const int COL = 2;  
const int SUB = 3;  
  
int encode(int type,int id,int num){  
    return type*81+id*9+num+1;  
}  
  
char mp[90];  

  
const int maxnode=270000;  
const int maxn=350;  
const int maxr=750;  

  
struct dlx{  
    #define FOR(i,A,s) for(int i = A[s];i!=s;i=A[i])  
    int n,sz;  
    int U[maxnode],D[maxnode],L[maxnode],R[maxnode];  
    int row[maxnode],col[maxnode];  
      
    int S[maxn];    //各列节点数   
    int ans[maxr];  
    int ansdep;  
      
    void init(int n){  
        this->n=n;  
        sz=0;  
        memset(S,0,sizeof(S));  
          
        for(int i=0;i<=n;i++){  
            U[i]=D[i]=i;  
            L[i]=i-1;    R[i]=i+1;  
            sz++;  
        }  
        L[0]=n;    R[n]=0;  
    }  
      
    void addrow(int r,vector<int> newrow){  
        int first=sz;  
        for(int i=0;i<newrow.size();i++){  
            int pos=newrow[i];  
            U[sz]=U[pos];    D[sz]=pos;  
            U[pos]=sz;  
            D[U[sz]]=sz;  
            row[sz]=r;  
            col[sz]=pos;  
            S[pos]++;  
            sz++;  
          
        }  
        for(int i=first;i<sz;i++){  
            L[i]=i-1;    R[i]=i+1;  
        }  
        L[first]=sz-1;    R[sz-1]=first;  
    }  
      
    void remove(int c){  
        R[L[c]]=R[c];  
        L[R[c]]=L[c];  
        FOR(i,D,c){  
            FOR(j,R,i){  
                U[D[j]]=U[j];    D[U[j]]=D[j];  
                --S[col[j]];  
            }  
        }  
    }  
      
    void restore(int c){  
        FOR(i,U,c){  
            FOR(j,L,i){  
                ++S[col[j]];  
                U[D[j]]=j;    D[U[j]]=j;  
            }  
        }  
        R[L[c]]=c;  
        L[R[c]]=c;  
    }  
      
    bool dfs(int d){  

        if(R[0]==0){  
            ansdep=d;  
            return 1;  
        }  
          
        int c=R[0];    //去满足一列   
        for(int i=c;i!=0;i=R[i]){  
            if(S[i]<S[c])c=i;  
        }  

        remove(c);  
        FOR(i,D,c){    //遍历这一列   
            ans[d]=row[i];  
            FOR(j,R,i){  
                remove(col[j]);  
            }  
            if(dfs(d+1))return 1;  
            FOR(j,L,i){  
                restore(col[j]);  
            }  
        }  
        restore(c);  
    	return 0;
	}  
}solver;  

  
int main(){  
    while(cin>>mp){  
		if(mp[0]=='e'&&mp[1]=='n'&&mp[2]=='d')break;
        solver.init(324);  
        for(int i=0;i<81;i++){ 
            for(int k=1;k<=9;k++){ 
				
                if(mp[i]==k+'0'||mp[i]=='.'){  
                    vector<int> vec;  
                    vec.push_back(encode(SLOT,i/9,i%9));  
                    vec.push_back(encode(ROW,i/9,k-1));  
                    vec.push_back(encode(COL,i%9,k-1));  
                    vec.push_back(encode(SUB,i/27*3+(i%9)/3,k-1));  
                    solver.addrow( i*9+k-1 ,vec);  
                }  
                
            }  
        }
        
        bool ok = solver.dfs(0);  
		
        for(int i=0;i<81;i++){  
            int tmp=solver.ans[i];  
            int pos=tmp/9;
            mp[pos]=tmp%9+1+'0';
        }  
        for(int i=0;i<81;i++){
        	printf("%c",mp[i]);
        }cout<<endl;
	}  
    return 0;        
}


你可能感兴趣的:(poj 3074 Sudoku)