题意:给一个16*16的只旋转4*4的矩阵的数独,求最少顺时针旋转多少次其中的4*4矩阵能把它还原?
分析:搜索加可行性剪枝即可通过。由于数独限制较强,剪枝效果良好。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=100000;
int ans;
int dx[6],a[6][6][6][6],sx[6],sy[6][6],dy[6];
char s[20][20];
void check(int ii,int x,int y) //翻转0到270度 求出每行每列的值
{
for(int i=0; i<4; i++)dx[i]=dy[i]=0;
if(ii==0)
{
for(int i=0; i<4; i++)
for(int j=0; j<=4; j++)
{
dx[i]|=a[x][y][i][j];
dy[j]|=a[x][y][i][j];
}
}
if(ii==1)
{
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
{
dx[j]|=a[x][y][i][j];
dy[i]|=a[x][y][i][j];
}
swap(dy[0],dy[3]);
swap(dy[1],dy[2]);
}
if(ii==2)
{
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
{
dx[i]|=a[x][y][i][j];
dy[j]|=a[x][y][i][j];
}
swap(dx[0],dx[3]);
swap(dx[1],dx[2]);
swap(dy[0],dy[3]);
swap(dy[1],dy[2]);
}
if(ii==3)
{
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
{
dx[j]|=a[x][y][i][j];
dy[i]|=a[x][y][i][j];
}
swap(dx[0],dx[3]);
swap(dx[1],dx[2]);
}
}
void dfs(int x,int y,int val)
{
if(x>4)
{
ans=min(ans,val);
return ;
}
for(int i=0; i<4; i++)
{
check(i,x,y);
bool flag=true;;
for(int j=0; j<4; j++)
{
if(sx[j]&dx[j]||sy[y][j]&dy[j])
{
flag=false;
}
}
if(flag)
{
val+=i;
int tx[5],ty[6];
for(int j=0; j<4; j++)tx[j]=sx[j],ty[j]=sy[y][j];
for(int j=0; j<4; j++)
sx[j]|=dx[j],sy[y][j]|=dy[j];
if(y==4)
{
for(int j=0; j<4; j++)sx[j]=0;
dfs(x+1,1,val);
}
else
dfs(x,y+1,val);
for(int j=0; j<4; j++)sx[j]=tx[j],sy[y][j]=ty[j];
val-=i;
}
}
}
int main()
{
int TA;
scanf("%d",&TA);
while(TA--)
{
for(int i=1; i<=16; i++)
scanf(" %s",s[i]+1);
for(int i=1; i<=4; i++)
for(int j=1; j<=4; j++)
for(int k=0,ii=i*4-4+1; ii<=i*4; ii++,k++)
for(int l=0,jj=j*4-4+1; jj<=j*4; jj++,l++)
if(s[ii][jj]<='9'&&s[ii][jj]>='0')
a[i][j][k][l]=(1<<(s[ii][jj]-'0'));
else
a[i][j][k][l]=(1<<(s[ii][jj]-'A'+10));
ans=INF;
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
dfs(1,1,0);
printf("%d\n",ans);
}
}