2018多校第4場1010 && HDU6341 ProblemJ. Let Sudoku Rotate
阿新 • • 發佈:2019-02-18
思路分析:大矩形分為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; }