• 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 (1T103) 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

    题意概括:

    有一个 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 }
    View Code
  • 相关阅读:
    makefile基础(GNU)
    7z命令行工具
    使用getopt函数对windows命令行程序进行参数解析
    在iMac机os x上装win7双系统经验心得
    windows操作技巧
    【SpringBoot】SpringBoot 整合RabbitMQ(二十)
    【RabbitMQ】 RabbitMQ 基本概念及测试
    【SpringBoot】SpringBoot 整合Redis缓存(十九)
    【SpringBoot】SpringBoot 自定义starter(十七)
    【SpringBoot】SpringBoot 事件监听机制(十六)
  • 原文地址:https://www.cnblogs.com/ymzjj/p/10342213.html
Copyright © 2020-2023  润新知