HDU-6341 Problem J. Let Sudoku Rotate(dfs 剪枝)

时间:2021-10-15 16:40:46

题目:有一个4*4*4*4的数独,每一横每一竖每一个小方块中都无重复的字母,即都为0-9,A-F.。有一个已经填好的数独,若干个4*4的方块被逆时针拧转了若干次,问拧转回来至少需要多少次。

分析:很明显的一道深授暴力题 , 一开始不知道是怎么收才好 , 那时候考虑说假如同一行或者同一列都有区域要反转 , 我该怎么找 , 后来看了题解后发现 , 我只要保证每次旋转后 , 该区域与此前的区域是满足数独的就好 , 子问题的不重复不会影响到大问题的不重复 。深搜索的能力需要加强

#include<bits/stdc++.h>
using namespace std ;
int G[][],tmp[][];
bool vis[];
int ans;
void rot(int x , int y)
{
for(int i=;i<=;i++)
for(int j=;j<=;j++)
tmp[j][-i+]=G[(x-)*+i][(y-)*+j];
for(int i=;i<=;i++)
for(int j=;j<=;j++)
G[(x-)*+i][(y-)*+j]=tmp[i][j];
} bool check(int x , int y)
{
for(int i=*x- ; i<=x* ; i++)
{
memset(vis,,sizeof(vis));
for(int j= ; j<=*y ; j++)
{
if(!vis[G[i][j]])
vis[G[i][j]]=;
else return ;
}
}
for(int i=y*- ; i<=y* ; i++)
{
memset(vis,,sizeof(vis));
for(int j= ; j<=*x ; j++)
{
if(!vis[G[j][i]])
vis[G[j][i]]=;
else return ;
}
}
return ;
}
void dfs(int x , int y , int sum)
{
if(ans<=sum)
return ;
int X=x , Y=y+;
if(x==)
{
ans=sum; return ;
}
if(Y==)
{
X++;
Y=;
}
for(int i= ; i< ; i++)
{
if(i) rot(x,y);
if(check(x,y))
{ //printf("520");
dfs(X,Y,sum+i);
} }
rot(x,y);
}
char s[];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
for(int i= ; i<= ; i++)
{
scanf("%s",s+);
for(int j= ; j<= ; j++)
{
if(s[j]>=''&&s[j]<='')
G[i][j]=s[j]-'';
else
G[i][j]=s[j]-'A'+;
}
} ans=0x3f3f3f3f;
dfs(,,);
printf("%d\n",ans);
}
return ;
}