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

Problem Description

Sudoku is a logic-based, combinatorial number-placement puzzle, which is popular around the world.
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?

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 Input

1
681D5A0C9FDBB2F7
0A734B62E167D9E5
5C9B73EF3C208410
F24ED18948A5CA63
39FAED5616400B74
D120C4B7CA3DEF38
7EC829A085BE6D51
B56438F129F79C2A
5C7FBC4E3D08719F
AE8B1673BF42A58D
60D3AF25619C30BE
294190D8EA57264C
C7D1B35606835EAB
AF52A1E019BE4306
8B36DC78D425F7C9
E409492FC7FA18D2

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 }

原文地址:https://www.cnblogs.com/ymzjj/p/10342213.html

时间: 2024-10-10 13:40:48

2018 Multi-University Training Contest 4 Problem J. Let Sudoku Rotate 【DFS+剪枝+矩阵旋转】的相关文章

HDU-6341 Problem J. Let Sudoku Rotate(dfs 剪枝)

题目:有一个4*4*4*4的数独,每一横每一竖每一个小方块中都无重复的字母,即都为0-9,A-F..有一个已经填好的数独,若干个4*4的方块被逆时针拧转了若干次,问拧转回来至少需要多少次. 分析:很明显的一道深授暴力题 , 一开始不知道是怎么收才好 , 那时候考虑说假如同一行或者同一列都有区域要反转 , 我该怎么找 , 后来看了题解后发现 , 我只要保证每次旋转后 , 该区域与此前的区域是满足数独的就好 , 子问题的不重复不会影响到大问题的不重复 .深搜索的能力需要加强 #include<bit

hdu6341 Problem J. Let Sudoku Rotate (dfs)

题目传送门 题意: 给你16个16宫格的数独,里面是0~F,你可以逆时针旋转里面的每个16宫格 问你它是从标准数独逆时针旋转多少次得到? 思路: 可以知道每个16宫已经是标准的了,接下来只要考虑每行.每列就行了 那么我们在dfs中就可以用两个行列两个数组来标记每个数字出现的次数, 大于1则不行 另外此时是逆时针来的,那么你就要顺时针回去 逆一次等于顺3次 参考博客:https://www.cnblogs.com/zquzjx/p/10326048.html 代码: #include<bits/s

hdu第4场j.Let Sudoku Rotate

Problem J. Let Sudoku Rotate Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 771 Accepted Submission(s): 417 Problem Description Sudoku is a logic-based, combinatorial number-placement puzzle, w

HDU 2018 Multi-University Training Contest 3 Problem A. Ascending Rating 【单调队列优化】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6319 Problem A. Ascending Rating Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 5943    Accepted Submission(s): 2004 Problem Description Before

2018 Multi-University Training Contest 4 Problem L. Graph Theory Homework 【YY】

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6343 Problem L. Graph Theory Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1536    Accepted Submission(s): 830 Problem Description Ther

2018 Multi-University Training Contest 4 Problem K. Expression in Memories 【模拟】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6342 Problem K. Expression in Memories Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 2150    Accepted Submission(s): 772Special Judge Problem De

2018 Nowcoder Multi-University Training Contest 2

Practice Link A. run 题意: 白云每次可以移动\(1\)米或者\(k\)米,询问移动的米数在\([L, R]\)范围内的方案数有多少. 思路: \(dp[i][2]\)表示到第\(i\)米,是通过\(1\)米的方式过来的还是\(k\)米的方式过来的,递推即可. 代码: #include <bits/stdc++.h> using namespace std; #define N 100010 const int p = 1e9 + 7; int f[N][2], g[N];

2018 Nowcoder Multi-University Training Contest 1

Practice Link J. Different Integers 题意: 给出\(n\)个数,每次询问\((l_i, r_i)\),表示\(a_1, \cdots, a_i, a_j, \cdots, a_n\)中有多少个不同的数. 思路: 先分别离线求出\(a_1, \cdots a_i\)以及\(a_j, \cdots, a_n\)中有多少个不同的数. 再考虑有多少个数既在\([1, i]\)中也在\([j, n]\)中,再离线做一次. 考虑一个数第一次出现的时候,那么这个数下一次出现

2018 Nowcoder Multi-University Training Contest 5

Practice Link A. gpa 题意: 有\(n\)门课程,每门课程的学分为\(s_i\),绩点为\(c_i\),要求最多删除\(k\)门课程,使得gpa最高. gpa计算方式如下: \[ \begin{eqnarray*} gpa = \frac{\sum s_ic_i}{\sum s_i} \end{eqnarray*} \] 思路: 首先删去的课程越多,gpa肯定不会变得更差. 所以我们肯定是删去\(k\)门课程. 考虑二分答案,check的时候要满足: \[ \begin{eq