poj3076 16*16soduku

思路
1.若某一个格子只有一种填法了 那就填上
2.若某个格子一种填法也没有 无解
3.若某行/列/宫格中某个字母的填法唯一 填上
4.若某行/列/宫格中某个字母不能填 无解

在以上的情况下 再选择可选选项最少的格子去填就行

最近做了几个搜索题,可以感觉到在一层dfs里多几个小的遍历没有关系 关键要让搜索树小才能快

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
char s[20][20];
char bs[300][20][20]; 
int col[20],row[20],cell[5][5];
int bcol[300][20],brow[300][20],bcell[300][5][5];
int bcol2[300][20],brow2[300][20],bcell2[300][5][5];
int map[1000005],ones[1000005];
int tot;
inline int lowbit(int x)
{
	return x&-x;
}

inline int get(int x,int y)
{
	if(s[x][y]!='-')return 1<<(s[x][y]-'A');
	return row[x]&col[y]&cell[x/4][y/4];
}

void draw(int x,int y,int z)
{
	row[x]-=z;
	col[y]-=z;
	cell[x/4][y/4]-=z;
	s[x][y]=map[z]+'A';
}
bool dfs(int x)
{
//	printf("%d\n",x);
	if(!x)return true;
	
	int kx=x;
	memcpy(brow[kx],row,sizeof(row));
	memcpy(bcol[kx],col,sizeof(col));
	memcpy(bcell[kx],cell,sizeof(cell));
	memcpy(bs[kx],s,sizeof(s));
	
	//格子 
	for(int i=0;i<16;++i)
	{
		for(int j=0;j<16;++j)
		{
			if(s[i][j]=='-')
			{
				int t=get(i,j);
				if(!t)
				{
					memcpy(row,brow[kx],sizeof(row));
					memcpy(col,bcol[kx],sizeof(col));
					memcpy(cell,bcell[kx],sizeof(cell));
					memcpy(s,bs[kx],sizeof(s));
					
					return false;
				}
				if(ones[t]==1)
				{
					draw(i,j,t);
					--x;
				}
			}
		}
	}
	//row
	for(int i=0;i<16;++i)
	{
		int sor=0,sand=(1<<16)-1,drawn=0;
		for(int j=0;j<16;++j)
		{
			int t=get(i,j);
			sand&=~(sor&t);
			sor|=t;
			if(s[i][j]!='-')drawn|=t;
		}
		if(sor!=(1<<16)-1)
		{
			memcpy(row,brow[kx],sizeof(row));
			memcpy(col,bcol[kx],sizeof(col));
			memcpy(cell,bcell[kx],sizeof(cell));
			memcpy(s,bs[kx],sizeof(s));
			return false;
		}
		for(int j=sand;j;j-=lowbit(j))
		{
			int t=lowbit(j);
			if(!(drawn&t))
			{
				for(int k=0;k<16;++k)
				{
					if(get(i,k)&t)
					{
						draw(i,k,t);
						--x;
						break;
					}
				}
			}
		}
	}
	//column
	for(int i=0;i<16;++i)
	{
		int sor=0,sand=(1<<16)-1,drawn=0;
		for(int j=0;j<16;++j)
		{
			int t=get(j,i);
			sand&=~(sor&t); 
			sor|=t;
			if(s[j][i]!='-')drawn|=t;
		}
		if(sor!=(1<<16)-1)
		{
			memcpy(row,brow[kx],sizeof(row));
			memcpy(col,bcol[kx],sizeof(col));
			memcpy(cell,bcell[kx],sizeof(cell));
			memcpy(s,bs[kx],sizeof(s));
			return false;
		}
		for(int j=sand;j;j-=lowbit(j))
		{
			int t=lowbit(j);
			if(!(drawn&t))
			{
				for(int k=0;k<16;++k)
				{
					if(get(k,i)&t)
					{
						draw(k,i,t);
						--x;
						break;
					}
				}
			}
		}
	}
	//cell
	for(int i=0;i<16;++i)
	{
		int sor=0,sand=(1<<16)-1,drawn=0;
		for(int j=0;j<16;++j)
		{
			int sx=i/4*4,sy=i%4*4;
			int dx=j/4,dy=j%4;
			int t=get(sx+dx,sy+dy);
			sand&=~(sor&t);
			sor|=t;
			if(s[sx+dx][sy+dy]!='-')drawn|=t;
		}
		
		if(sor!=(1<<16)-1)
		{
			memcpy(row,brow[kx],sizeof(row));
			memcpy(col,bcol[kx],sizeof(col));
			memcpy(cell,bcell[kx],sizeof(cell));
			memcpy(s,bs[kx],sizeof(s));
			return false;
		}
		for(int j=sand;j;j-=lowbit(j))
		{
			int t=lowbit(j);
			if(!(drawn&t))
			{
				for(int k=0;k<16;++k)
				{
					int sx=i/4*4,sy=i%4*4;
					int dx=k/4,dy=k%4;
					if(get(sx+dx,sy+dy)&t)
					{
						draw(sx+dx,sy+dy,t);
						--x;
						break;
					}
				}
			}
		}
	}
	if(!x)return true;
	//normal choose
	int minn=100,mx,my;
	for(int i=0;i<16;++i)
	{
		for(int j=0;j<16;++j)
		{
			if(s[i][j]=='-'&&ones[get(i,j)]<minn)
			{
				minn=ones[get(i,j)];
				mx=i,my=j;
			}
		}
	}
	memcpy(brow2[kx],row,sizeof row);
	memcpy(bcol2[kx],col,sizeof col);
	memcpy(bcell2[kx],cell,sizeof cell);
	for(int i=get(mx,my);i;i-=lowbit(i))
	{
		int k=lowbit(i);
		memcpy(row,brow2[kx],sizeof row);
		memcpy(col,bcol2[kx],sizeof col);
		memcpy(cell,bcell2[kx],sizeof cell);
		draw(mx,my,k);
		
		if(dfs(x-1))return true;
	}
	
	memcpy(row,brow[kx],sizeof(row));
	memcpy(col,bcol[kx],sizeof(col));
	memcpy(cell,bcell[kx],sizeof(cell));
	memcpy(s,bs[kx],sizeof(s));
	
	return false;
}
int main()
{
	for(int i=0;i<16;++i)
	{
		map[1<<i]=i;
	}
	for(int i=0;i<1<<16;++i)
	{
		for(int j=i;j;j-=lowbit(j))++ones[i];
	}
		
	while(scanf("%s",s[0])!=EOF)
	{
		for(int i=0;i<16;++i)
		{
			col[i]=row[i]=(1<<16)-1;
		}
		for(int i=0;i<4;++i)
		{
			for(int j=0;j<4;++j)
			{
				cell[i][j]=(1<<16)-1;
			}
		}
	
		for(int i=1;i<16;++i)scanf("%s",s[i]);
		
		int cnt=0;
		for(int i=0;i<16;++i)
		{	
			for(int j=0;j<16;++j)
			{
				if(s[i][j]!='-')
				{
					draw(i,j,1<<(s[i][j]-'A'));
				}
				else ++cnt;
			}
		}
		if(!dfs(cnt))printf("ERROR\n");
		else for(int i=0;i<16;++i)printf("%s\n",s[i]);
		printf("\n");
	}
	return 0;
}
发布了25 篇原创文章 · 获赞 1 · 访问量 294

猜你喜欢

转载自blog.csdn.net/qq_43665203/article/details/104266858