HDU6341 Problem J. Let Sudoku Rotate(2018HDU多校联赛第四场,数独,DFS)

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.
img
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.

img

思路

题目给出了一个16*16的数独,其中有16个宫,题目问你至少逆时针旋转其中的宫几次,可以使这个数独合法。

数独合法的定义是:

  1. 每一行和每一列中不能有重复的数字
  2. 每一个宫里面不能有重复的数字

因为题目给出的有数字还有字符,我们先转换一下使得全部变成数字,然后按照这16个宫的顺序去搜索,搜索的时候判断一下,当前宫所在的位置之前的每一行和每一列是否有重复的,如果当前宫可以不翻转,就搜索下一个,否则就翻转继续搜索。加两个剪枝就过了。

比较坑的就是,给出的样例和给出的图竟然不是同一个..

代码

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
const int N = 20;
char s[N][N];
int a[N][N], minn;
int vis[N];

void rot(int x, int y)
{
    int t[5][5];
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            t[j][3 - i] = a[x + i][y + j];
    for (int i = 0; i < 4; i++)
        for (int j = 0; j < 4; j++)
            a[x + i][y + j] = t[i][j];
}
int check(int x, int y)
{
    for (int i = x; i < x + 4; i++)
    {
        mem(vis, 0);
        for (int j = 0; j < y + 4; j++)
        {
            vis[a[i][j]]++;
            if (vis[a[i][j]] >= 2)
                return 0;
        }
    }
    for (int i = y; i < y + 4; i++)
    {
        mem(vis, 0);
        for (int j = 0; j < x + 4; j++)
        {
            vis[a[j][i]]++;
            if (vis[a[j][i]] >= 2)
                return 0;
        }
    }
    return 1;
}
void dfs(int i, int j, int step)
{
    if (i == 4)
    {
        minn = min(minn, step);
        return;
    }
    if (step >= minn)
        return;
    if (j == 4)
        dfs(i + 1, 0, step);
    for (int t = 0; t < 4; t++)
    {
        if (check(i * 4, j * 4)) //如果不需要翻转
            dfs(i, j + 1, step + t);
        rot(i * 4, j * 4);
    }
}
void solve()
{
    for (int i = 0; i < 16; i++)
    {
        scanf("%s", s[i]);
        for (int j = 0; j < 16; j++)
        {
            if (isdigit(s[i][j]))
                a[i][j] = s[i][j] - '0';
            else
                a[i][j] = s[i][j] - 'A' + 10;
        }
    }
    minn = 16 * 4;
    dfs(0, 0, 0);
    printf("%d\n", minn);
}
int main()
{
    //freopen("in.txt", "r", stdin);
    int t;
    scanf("%d", &t);
    while (t--)
        solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/riba2534/article/details/81407169
今日推荐