2018 Multi-University Training Contest 4 Problem J. Let Sudoku Rotate 【DFS+剪枝+矩陣旋轉】
阿新 • • 發佈:2019-01-31
mage object ati oid key scrip dig C4D cde
In this problem, let us focus on puzzles with 16×16 grids, which consist of 4×4 regions. The objective is to fill the whole grid with hexadecimal digits, i.e. 0123456789ABCDEF, so that each column, each row, and each region contains all hexadecimal digits. The figure below shows a solved sudoku.
Yesterday, Kazari solved a sudoku and left it on the desk. However, Minato played a joke with her - he performed the following operation several times.
* Choose a region and rotate it by 90 degrees counterclockwise.
She burst into tears as soon as she found the sudoku was broken because of rotations.
Could you let her know how many operations her brother performed at least?
Each test case consists of exactly 16 lines with 16 characters each, describing a broken sudoku.
Sample Input
1
681D5A0C9FDBB2F7
0A734B62E167D9E5
5C9B73EF3C208410
F24ED18948A5CA63
39FAED5616400B74
D120C4B7CA3DEF38
7EC829A085BE6D51
B56438F129F79C2A
5C7FBC4E3D08719F
AE8B1673BF42A58D
60D3AF25619C30BE
294190D8EA57264C
C7D1B35606835EAB
AF52A1E019BE4306
8B36DC78D425F7C9
E409492FC7FA18D2
任意門:http://acm.hdu.edu.cn/showproblem.php?pid=6341
Problem J. Let Sudoku Rotate
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1363 Accepted Submission(s): 717
In this problem, let us focus on puzzles with 16×16
Yesterday, Kazari solved a sudoku and left it on the desk. However, Minato played a joke with her - he performed the following operation several times.
* Choose a region and rotate it by 90 degrees counterclockwise.
She burst into tears as soon as she found the sudoku was broken because of rotations.
Could you let her know how many operations her brother performed at least?
Input The first line of the input contains an integer T (1≤T≤103) denoting the number of test cases.
Each test case consists of exactly 16 lines with 16 characters each, describing a broken sudoku.
Output For each test case, print a non-negative integer indicating the minimum possible number of operations.
Sample Output 5 Hint The original sudoku is same as the example in the statement.
Source 2018 Multi-University Training Contest 4
題意概括:
有一個 16×16 的已經打亂的數獨,4×4為一宮,每次可對宮順時針旋轉 90 度。最少要操作多少次可以還原數獨。
解題思路:
遞歸每一宮的左上角坐標 (x, y) ,DFS枚舉每一宮的旋轉次數,可知這樣暴力的方案數為 4^(16) = 4294967296,需要剪枝。
由於數獨的特殊性,我們枚舉下一個狀態前可以先判斷上一個狀態是否滿足條件,即每行每列的數都要單獨存在。
對於矩陣旋轉的操作,找一下下標的規律:第一行變成第一列,第二行變成第二列,第三行變成第三列.....
AC code:
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<vector> 6 #include<queue> 7 #include<cmath> 8 #include<set> 9 #define INF 0x3f3f3f3f 10 #define LL long long 11 using namespace std; 12 const int MAXN = 20; 13 char str[MAXN][MAXN]; 14 int mmp[MAXN][MAXN]; 15 int tmp[MAXN][MAXN]; 16 bool vis[MAXN]; 17 int ans; 18 19 void rt(int x, int y) 20 { 21 int rx = 4*x, ry = 4*y-3; 22 for(int i = 4*x-3; i <= 4*x; i++){ 23 rx = 4*x; 24 for(int k = 4*y-3; k <= 4*y; k++){ 25 tmp[i][k] = mmp[rx][ry]; 26 rx--; 27 } 28 ry++; 29 } 30 31 for(int i = 4*x-3; i <= 4*x; i++){ 32 for(int j = 4*y-3; j <= 4*y; j++){ 33 mmp[i][j] = tmp[i][j]; 34 } 35 } 36 37 } 38 39 bool check(int x, int y) 40 { 41 for(int i = 4*x-3; i <= 4*x; i++){ 42 memset(vis, 0, sizeof(vis)); 43 for(int j = 1; j <= 4*y; j++){ 44 if(vis[mmp[i][j]]){ 45 return false; 46 } 47 vis[mmp[i][j]] = true; 48 } 49 } 50 for(int i = 4*y-3; i <= 4*y; i++){ 51 memset(vis, 0, sizeof(vis)); 52 for(int j = 1; j <= 4*x; j++){ 53 if(vis[mmp[j][i]]){ 54 return false; 55 } 56 vis[mmp[j][i]] = true; 57 } 58 } 59 return true; 60 } 61 62 void dfs(int x, int y, int cnt) 63 { 64 if(x > 4){ 65 ans = min(ans, cnt); 66 return; 67 } 68 for(int i = 0; i < 4; i++){ 69 if(i) rt(x, y); 70 if(check(x, y)){ 71 if(y < 4) dfs(x, y+1, cnt+i); 72 else dfs(x+1, 1, cnt+i); 73 } 74 } 75 rt(x, y); 76 } 77 78 int main() 79 { 80 int T_case; 81 scanf("%d", &T_case); 82 while(T_case--){ 83 for(int i = 0; i < 16; i++){ 84 scanf("%s", str[i]); 85 } 86 for(int i = 0; i < 16; i++){ 87 for(int j = 0; j < 16; j++){ 88 if(str[i][j] >= ‘0‘ && str[i][j] <= ‘9‘){ 89 mmp[i+1][j+1] = str[i][j]-‘0‘; 90 } 91 else mmp[i+1][j+1] = str[i][j]-‘A‘+10; 92 } 93 } 94 ans = INF; 95 dfs(1, 1, 0); 96 printf("%d\n", ans); 97 } 98 return 0; 99 }View Code
2018 Multi-University Training Contest 4 Problem J. Let Sudoku Rotate 【DFS+剪枝+矩陣旋轉】