HDU6341 Problem J. Let Sudoku Rotate

Problem J. Let Sudoku Rotate

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)

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

Recommend

chendu | We have carefully selected several similar problems for you: 6343 6342 6341 6340 6339

Solution

When I was struggling on this problem with my TLE of 1000*(4^16), I could only think of the technique of optimality pruning.
大搜索,DFS。在听杜教的讲解前,我没想到还有这样的可行性剪枝,即每一个4*4小格子都可以判断一下是否还需旋转九十度:若是此小格子与它前面的每行都不冲突,与它前面的每一列都不冲突,则这个小格子不需要旋转九十度。
我之前居然把判断条件错写成:判断每一个4*4的小格子,是否与除它以外的前面和后面的每一行每一列是否冲突……如此不T才怪呢。
void DFS() 可以 return DFS();

Code

#include <bits/stdc++.h>

#define ll long long
using namespace std;
const int N = 20;
int T, ans, tot;
char st[N][N], tmp[N][N];
int vis[N];

void rot(int x, int y) {
    for (int i = x; i < x + 4; ++i)
        for (int j = y; j < y + 4; ++j)
            tmp[x + j % 4][y + 3 - i % 4] = st[i][j];

    for (int i = x; i < x + 4; ++i)
        for (int j = y; j < y + 4; ++j)
            st[i][j] = tmp[i][j];
}

bool check(int a, int b) {
    for (int i = a; i < a + 4; ++i) {
        tot++;
        for (int j = 0; j < b+4; ++j) {
            if (vis[st[i][j]] == tot)
                return 0;
            vis[st[i][j]] = tot;
        }
    }
    for (int i = b; i < b + 4; ++i) {
        tot++;
        for (int j = 0; j < a+4; ++j) {
            if (vis[st[j][i]] == tot)
                return 0;
            vis[st[j][i]] = tot;
        }
    }
    return 1;
}

void dfs(int x, int y, int sum) {
    if (sum>=ans) return ;
    if (x == 4) {
        ans = min(ans, sum);
        return;
    }
    if (y == 4) {
        dfs(x+1,0,sum);
        return ;
        //return dfs(x + 1, 0, sum);
    }
    for (int i = 0; i < 4; ++i) {
        if (check(x*4,y*4)) dfs(x,y+1,sum+i);
        rot(x*4,y*4);
    }
}

int main() {
    scanf("%d", &T);
    while (T--) {
        for (int i = 0; i < 16; ++i) scanf("%s", st[i]);
        for (int i = 0; i < 16; ++i)
            for (int j = 0; j < 16; ++j)
                if (isdigit(st[i][j])) st[i][j] -= 48;
                else st[i][j] -= 55;
        //printf("-----------------------------------------------\n");
        ans = 50;
        dfs(0, 0, 0);
        printf("%d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ACM2017/article/details/81350991
今日推荐