2018 Multi-University Training Contest 4 Problem J. Let Sudoku Rotate DFS+剪枝+矩阵旋转
Posted ymzjj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018 Multi-University Training Contest 4 Problem J. Let Sudoku Rotate DFS+剪枝+矩阵旋转相关的知识,希望对你有一定的参考价值。
任意门: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 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.
* 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.
题意概括:
有一个 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 ", ans); 97 } 98 return 0; 99 }
以上是关于2018 Multi-University Training Contest 4 Problem J. Let Sudoku Rotate DFS+剪枝+矩阵旋转的主要内容,如果未能解决你的问题,请参考以下文章
2018 Multi-University Training Contest 2
2018 Multi-University Training Contest 9
2018 Multi-University Training Contest 4
2018 Multi-University Training Contest 4