思路
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;
}