题目链接:Let Sudoku Rotate
思路分析:大矩形分为16个子块,搜索即可。数独限制性很强,可行性剪枝+最优化剪枝....
看了一下标程,写的很精简,学习了...
代码如下:
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int maxn = 20;
char s[maxn][maxn];
int a[maxn][maxn];
int b[10][10];
int row[maxn][maxn],col[maxn][maxn];
int ans;
inline int getc(char c){
if (isdigit(c)) return c-'0';
return c-'A'+10;
}
inline int Min(int x, int y) {return x<y?x:y;}
inline void add(int idx, int idy, int val) {
for (int i=idx<<2; i<(idx+1)<<2; ++i) {
for (int j=idy<<2; j<(idy+1)<<2; ++j)
row[i][a[i][j]] += val, col[j][a[i][j]] += val;
}
}
inline int Rotate(int idx, int idy) {
for (int i=idx<<2; i<(idx+1)<<2; ++i) {
for (int j=idy<<2; j<(idy+1)<<2; ++j) {
--row[i][a[i][j]]; --col[j][a[i][j]];
b[j-(idy<<2)][((idx+1)<<2)-i-1] = a[i][j];
}
}
int res = 1;
for (int i=idx<<2; i<(idx+1)<<2; ++i) {
for (int j=idy<<2; j<(idy+1)<<2; ++j) {
a[i][j] = b[i-(idx<<2)][j-(idy<<2)];
if ( (++row[i][a[i][j]]>1) || (++col[j][a[i][j]]>1) ) res = 0;
}
}
return res;
}
void dfs(int idx,int idy, int num){
if (idx>=4) {
ans = Min(ans,num);
return ;
}
if (num >= ans) return;
add(idx,idy,1);
for (int i=1; i<=4; ++i) {
if (Rotate(idx,idy)) dfs(idy == 3?idx+1:idx,idy == 3?0:idy+1,num+i%4);
}
add(idx,idy,-1);
}
int main(){
int T; scanf("%d",&T);
register int i,j;
while (T--){
for (i=0; i<16; ++i) {
scanf("%s",s[i]);
for (j=0; j<16; ++j) a[i][j] = getc(s[i][j]);
}
/*for (i=0; i<16; ++i) {
for (j=0; j<16; ++j) printf("%d",a[i][j]); puts("");
}*/
memset(row,0,sizeof(row));
memset(col,0,sizeof(col));
ans = 1<<30;
dfs(0,0,0);
printf("%d\n",ans);
}
return 0;
}