【DLX算法】poj2676 Sudoku

DLX算法求解精确覆盖问题模板。赛场上可以参见白书。

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int sub[10][10]={
{0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,2,2,2,3,3,3},
{0,1,1,1,2,2,2,3,3,3},
{0,1,1,1,2,2,2,3,3,3},
{0,4,4,4,5,5,5,6,6,6},
{0,4,4,4,5,5,5,6,6,6},
{0,4,4,4,5,5,5,6,6,6},
{0,7,7,7,8,8,8,9,9,9},
{0,7,7,7,8,8,8,9,9,9},
{0,7,7,7,8,8,8,9,9,9}
};
int hlb[12],hub[12],llb[12],lub[12];
const int maxn=4*9*9+5;
const int maxr=9*9*9+5;
const int maxnode=9*9*9*4+maxn+5;
//ÐбàºÅ´Ó1¿ªÊ¼£¬ÁбàºÅΪ1~n£¬½áµã0ÊDZíÍ·½áµã£»½áµã1~nÊǸ÷Áж¥²¿µÄÐéÄâ½áµã 
struct DLX{
	int n,sz;//ÁÐÊý£¬½áµã×ÜÊý 
	int S[maxn];//¸÷ÁнáµãÊý 
	int row[maxnode],col[maxnode];//¸÷½áµãËùÔÚµÄÐÐÁбàºÅ 
	int L[maxnode],R[maxnode],U[maxnode],D[maxnode];
	int ansd,ans[maxr];//½â 
	void init(int n){//nÊÇÁÐÊý 
		this->n=n;
		for(int i=0;i<=n;++i){
			U[i]=i;
			D[i]=i;
			L[i]=i-1;
			R[i]=i+1;
		}
		R[n]=0; L[0]=n;
		sz=n+1;
		memset(S,0,sizeof(S));
	}
	void addRow(int r,vector<int> columns){
		int first=sz;
		for(int i=0;i<columns.size();++i){
			int c=columns[i];
			L[sz]=sz-1;
			R[sz]=sz+1;
			D[sz]=c;
			U[sz]=U[c];
			D[U[c]]=sz;
			U[c]=sz;
			row[sz]=r;
			col[sz]=c;
			++S[c];
			++sz;
		}
		R[sz-1]=first;
		L[first]=sz-1;
	}
	//˳×ÅÁ´±íA£¬±éÀú³ýsÍâµÄÆäËûÔªËØ 
	#define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])
	void remove(int c){
		L[R[c]]=L[c];
		R[L[c]]=R[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;
			}
		}
		L[R[c]]=c;
		R[L[c]]=c;
	}
	bool dfs(int d){
//		printf("%d",d);
		if(R[0]==0){//ÕÒµ½½â 
			ansd=d;//¼Ç¼½âµÄ³¤¶È 
			return 1;
		}
		//ÕÒ½áµãÊý×îСµÄÁÐc 
		int c=R[0];//µÚÒ»¸öδɾ³ýµÄÁÐ 
		FOR(i,R,0){
			if(S[i]<S[c]){
				c=i;
			}
		}
		remove(c);//ɾ³ýµÚcÁÐ 
		FOR(i,D,c){//ÓýáµãiËùÔÚÐи²¸ÇµÚcÁÐ 
			ans[d]=row[i];
			FOR(j,R,i){
				remove(col[j]);//ɾ³ý½áµãiËùÔÚÐÐÄܸ²¸ÇµÄËùÓÐÆäËûÁÐ 
			}
			if(dfs(d+1)){
				return 1;
			}
			FOR(j,L,i){
				restore(col[j]);//»Ö¸´½áµãiËùÔÚÐÐÄܸ²¸ÇµÄÆäËûËùÓÐÁÐ 
			}
		}
		restore(c);//»Ö¸´µÚcÁÐ 
		return 0;
	}
	bool solve(vector<int>& v){
		v.clear();
		if(!dfs(0)){
			return 0;
		}
		for(int i=0;i<ansd;++i){
			v.push_back(ans[i]);
		}
		return 1;
	}
}dlx;
char s[12][12];
int a[12][12];
int mah[1005],mal[1005],mav[1005];
int encode(int a,int b,int c){
    return a*81+b*9+c+1;
}
void decode(int code,int &a,int &b,int &c){
    --code;
    c=code%9;code/=9;
    b=code%9;code/=9;
    a=code;
}  
int main(){
	int zu;
//	freopen("poj2676.in","r",stdin);
//	freopen("poj2676.out","w",stdout);
	memset(hlb,0x7f,sizeof(hlb));
	memset(llb,0x7f,sizeof(llb));
	for(int i=1;i<=9;++i){
		for(int j=1;j<=9;++j){
			hlb[sub[i][j]]=min(hlb[sub[i][j]],i);
			hub[sub[i][j]]=max(hub[sub[i][j]],i);
			llb[sub[i][j]]=min(llb[sub[i][j]],j);
			lub[sub[i][j]]=max(lub[sub[i][j]],j);
		}
	}
	scanf("%d",&zu);
	for(;zu;--zu){
		for(int i=1;i<=9;++i){
			scanf("%s",s[i]+1);
		}
		int hang=0,lie=0;
		for(int i=1;i<=9;++i){
			for(int j=1;j<=9;++j){
				a[i][j]=s[i][j]-'0';
			}
		}
		dlx.init(9*9*4);
		for(int i=1;i<=9;++i){
			for(int j=1;j<=9;++j){
				for(int k=1;k<=9;++k){
					if(!a[i][j] || a[i][j]==k){
						vector<int> columns;
						columns.push_back(encode(0,i-1,j-1));
						columns.push_back(encode(1,i-1,k-1));
						columns.push_back(encode(2,j-1,k-1));
						columns.push_back(encode(3,sub[i][j]-1,k-1));
						dlx.addRow(encode(i-1,j-1,k-1),columns);
					}
				}
			}
		}
		vector<int> ans;
		dlx.solve(ans);
		for(int i=0;i<ans.size();++i){
			int r,c,v;
			decode(ans[i],r,c,v);
			a[r+1][c+1]=v+1;
		}
		for(int i=1;i<=9;++i){
			for(int j=1;j<9;++j){
				printf("%d",a[i][j]);
			}
			printf("%d\n",a[i][9]);
		}
	}
	return 0;
}
posted @ 2017-10-30 00:07  AutSky_JadeK  阅读(292)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト