【POJ3076】Sudoku DLX(Dancing Links)

呼叫模板题:http://blog.csdn.net/vmurder/article/details/40622943

题解直接看这篇博客吧,都是一样的。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 4200
#define M 1100
#define NN 20000
#define inf 0x3f3f3f3f

#define Li_Sdk 4
#define Gi_Sdk 16
#define Su_Sdk 256
using namespace std;
char TS[Gi_Sdk+1][Gi_Sdk+1];
struct DLX
{
	int elist,eline;
	int id[Gi_Sdk+1][Gi_Sdk+1][Gi_Sdk+1];
	int eid[4][Gi_Sdk][Gi_Sdk];
	bool map[M][N];

	int U[NN],D[NN],L[NN],R[NN],C[NN],V[NN];
	int H[N],T[M],cnt;
	int ans[Gi_Sdk][Gi_Sdk];

	inline void init()
	{
		int i,j,k,_i,_j;
		for(i=1;i<=Gi_Sdk;i++)
			for(j=1;j<=Gi_Sdk;j++)
				for(k=1;k<=Gi_Sdk;k++)
					id[i][j][k]=++eline;
		for(i=1;i<=Gi_Sdk;i++)/*行*/
		{
			for(j=1;j<=Gi_Sdk;j++)/*数*/
			{
				int A=eid[0][i][j]=++elist;
				for(k=1;k<=Gi_Sdk;k++)/*列*/
				{
					int B=id[i][k][j];
					map[A][B]=1;
				}
			}
		}
		for(i=1;i<=Gi_Sdk;i++)/*列*/
		{
			for(j=1;j<=Gi_Sdk;j++)/*数*/
			{
				int A=eid[1][i][j]=++elist;
				for(k=1;k<=Gi_Sdk;k++)/*行*/
				{
					int B=id[k][i][j];
					map[A][B]=1;
				}
			}
		}
		for(i=0;i<Li_Sdk;i++)for(j=0;j<Li_Sdk;j++)/*十六宫格*/
		{
			for(k=1;k<=Gi_Sdk;k++)/*数*/
			{
				int A=eid[2][i*Li_Sdk+j+1][k]=++elist;
				for(_i=1;_i<=Li_Sdk;_i++)for(_j=1;_j<=Li_Sdk;_j++)/*格内点*/
				{
					int B=id[i*Li_Sdk+_i][j*Li_Sdk+_j][k];
					map[A][B]=1;
				}
			}
		}
		for(i=1;i<=Gi_Sdk;i++)for(j=1;j<=Gi_Sdk;j++)/*点的位置*/
		{
			int A=eid[3][i][j]=++elist;
			for(k=1;k<=Gi_Sdk;k++)/*点的9个数*/
			{
				int B=id[i][j][k];
				map[A][B]=1;
			}
		}
	}
	inline void clear()
	{
		cnt=0;
		memset(U,0,sizeof(U));
		memset(D,0,sizeof(D));
		memset(L,0,sizeof(L));
		memset(R,0,sizeof(R));
		memset(C,0,sizeof(C));
		memset(H,0,sizeof(H));
		memset(T,0,sizeof(T));
		memset(ans,0,sizeof(ans));
	}
	inline void newnode(int x,int y)
	{
		C[++cnt]=y;V[cnt]=x;T[y]++;

		if(!H[x])H[x]=L[cnt]=R[cnt]=cnt;
		else L[cnt]=H[x],R[cnt]=R[H[x]];
		R[H[x]]=L[R[H[x]]]=cnt,H[x]=cnt;

		U[cnt]=U[y],D[cnt]=y;
		U[y]=D[U[y]]=cnt;
	}
	inline void remove(int x)
	{
		for(int i=D[x];i!=x;i=D[i])
		{
			for(int j=R[i];j!=i;j=R[j])
			{
				U[D[j]]=U[j];
				D[U[j]]=D[j];
				T[C[j]]--;
			}
		}
		L[R[x]]=L[x];
		R[L[x]]=R[x];
	}
	inline void resume(int x)
	{
		for(int i=U[x];i!=x;i=U[i])
		{
			for(int j=L[i];j!=i;j=L[j])
			{
				U[D[j]]=j;
				D[U[j]]=j;
				T[C[j]]++;
			}
		}
		L[R[x]]=x;
		R[L[x]]=x;
	}
	inline void build()
	{
		clear();
		int i,j,k;
		cnt=4*Su_Sdk;
		for(i=1;i<=cnt;i++)
		{
			U[i]=D[i]=i;
			L[i]=L[0],R[i]=0;
			L[0]=R[L[0]]=i;
		}
		for(i=1;i<=Gi_Sdk;i++)for(j=1;j<=Gi_Sdk;j++)
		{
			int get=(i-1)*Gi_Sdk+j-1;
			if(TS[i][j]=='-')
			{
				for(k=get*Gi_Sdk+1;k<=get*Gi_Sdk+Gi_Sdk;k++)
					for(int temp=1;temp<=elist;temp++)
						if(map[temp][k])newnode(k,temp);
			}
			else
			{
				k=get*Gi_Sdk+TS[i][j]-'A'+1;
				for(int temp=1;temp<=elist;temp++)
					if(map[temp][k])newnode(k,temp);
			}
		}
	}
	inline bool dfs()
	{
		if(!R[0])return true;
		int S=R[0],W=T[S],i,j;
		for(i=R[S];i;i=R[i])if(T[i]<W)
		{
			W=T[i];
			S=i;
		}
		remove(S);
		for(i=D[S];i!=S;i=D[i])
		{
			ans[(V[i]-1)/Su_Sdk+1][((V[i]-1)/Gi_Sdk)%Gi_Sdk+1]=(V[i]-1)%Gi_Sdk+1;
			for(j=R[i];j!=i;j=R[j])remove(C[j]);
			if(dfs())return true;
			for(j=L[i];j!=i;j=L[j])resume(C[j]);
		}
		resume(S);
		return false;
	}
	inline void ret()
	{
		for(int i=1;i<=Gi_Sdk;i++)
		{
			for(int j=1;j<=Gi_Sdk;j++)
				printf("%c",ans[i][j]+'A'-1);
			puts("");
		}
	}
}dlx;
int main()
{
//	freopen("test.in","r",stdin);
//	freopen("my.out","w",stdout);
	dlx.init();
	while(1)
	{
		if(scanf("%s",TS[1]+1)==EOF)break;
		for(int i=2;i<=Gi_Sdk;i++)scanf("%s",TS[i]+1);
		dlx.build();
		dlx.dfs();
		dlx.ret();
		puts("");
	}
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值