Let Sudoku Rotate
题目传送门
思路:每个4X4的方块要么不旋转,要么旋转3次,所以对每个方块旋转次数进行dfs,再通过剪枝优化时间复杂度。剪枝优化是通过判断当前方块的旋转是否影响这个方块所在的列与行的前一部分,如果有冲突那就没有必要继续搜下去。
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <algorithm>
#include <functional>
#define inf 1000000000
using namespace std;
typedef long long ll;
const int MAXN=1e9+10;
const int MAX=1e2+10;
const double eps=1e-6;
int ans;
int G[MAX][MAX];
int temp[10][10];
bool vis[MAX];
bool juge(int x,int y){
for(int i=x*4-3;i<=x*4;i++){
memset(vis,0,sizeof(vis));
for(int j=1;j<=y*4;j++){
if(vis[G[i][j]]) return false;
else vis[G[i][j]]=true;
}
}
for(int j=y*4-3;j<=y*4;j++){
memset(vis,0,sizeof(vis));
for(int i=1;i<=x*4;i++){
if(vis[G[i][j]]) return false;
else vis[G[i][j]]=true;
}
}
return true;
}
void rot(int x,int y){
for(int i=1;i<=4;i++){
for(int j=1;j<=4;j++){
temp[j][4-i+1]=G[(x-1)*4+i][(y-1)*4+j];
}
}
for(int i=1;i<=4;i++){
for(int j=1;j<=4;j++){
G[(x-1)*4+i][(y-1)*4+j]=temp[i][j];
}
}
}
void dfs(int x,int y,int num){
if(num>ans) return;
if(x==5){
ans=min(ans,num);
return ;
}
int xt=x,yt=y+1;
if(yt>4){
yt=1;xt++;
}
for(int i=0;i<4;i++){
if(i) rot(x,y);
if(juge(x,y))
dfs(xt,yt,num+i);
}
rot(x,y);
}
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("in.txt","r",stdin);
#endif
int T;
cin>>T;
while(T--){
char s[100];
ans=16*4;
for(int i=1;i<=16;i++){
scanf("%s",s);
for(int j=0;j<16;j++){
if(s[j]>='0'&&s[j]<='9')
G[i][j+1]=s[j]-'0';
else
G[i][j+1]=s[j]-'A'+10;
}
}
dfs(1,1,0);
cout<<ans<<endl;
}
return 0;
}