解题报告:其实这题我以前做过,但是我给忘记了怎么剪枝,刚好蓝桥杯训练到了这题,那就补一补吧,主要是要把行、列、3x3小矩阵这三个信息的状态压缩,然后某点x,y可选的值在他们状态相与的情况下才满足,然后每次搜索,搜索分支最小的搜索,还有个小优化就是lowbit运算,返回二进制最近的1的数值,然后还要预处理出来1<<i的值就可以了。
#include<iostream>
using namespace std;
string str;
const int N=9;
int one[1<<N],map[1<<N];
int row[N],col[N],g[N/3][N/3];
int lowbit(int x)
{
return x&-x;
}
int get(int x,int y)
{
return row[x]&col[y]&g[x/3][y/3];
}
void init()
{
for(int i=0;i<N;i++)
{
row[i]=(1<<N)-1;
col[i]=(1<<N)-1;
}
for(int i=0;i<N/3;i++)
for(int j=0;j<N/3;j++)
g[i][j]=(1<< N )-1;
}
bool dfs(int cnt)
{
if(!cnt) return true;
int minv=10;
int x=0,y=0;
for(int i=0;i<N;i++)
for (int j=0; j<N; j++)
{
if(str[i*N+j]=='.')
{
int t=one[get(i,j)];
if(t<minv)
{
minv=t;
x=i;
y=j;
// cout<<x<<' '<<y<<endl;
}
}
}
int tt=get(x,y);
// cout<<x<<' '<<y<<endl;
// cout<<t<<endl;
for(int i=tt ;i ;i-=lowbit(i))
{
int bb=map[lowbit(i)];
row[x]-=1<<bb;
col[y]-= 1<<bb;
g[x/3][y/3] -= 1<<bb;
char cc='1'+bb;
str[x*N+y]=cc;
if(dfs(cnt-1)) return true;
str[x*N+y]='.';
row[x]+= 1<<bb;
col[y]+=1<<bb;
g[x/3][y/3] += 1<<bb;
}
return false;
}
int main()
{
for(int i=0;i< N;i++) map[1<<i]=i;
for(int i=0;i<1<<N;i++)
for(int j=0;j<N;j++)
if((i>>j)&1) one[i]++;
// exit(0);
while(cin>> str , str != "end")
{
int cnt=0;
init();
for(int i=0;i<str.size();i++)
{
if(str[i]!='.')
{
int t=str[i]-'1';
// cout<<t<<endl;
row[i/N] -= 1<<t;
col[i%N] -= 1<<t;
int tx=i/N;
int ty=i%N;
g[tx/3][ty/3] -= 1<<t;
}
else
cnt++;
}
// cout<<1<<N-1<<' '<<(1<<N)-1<<endl;
// cout<<cnt<<endl;
dfs(cnt); //exit(0);
cout<<str<<endl;
}
}