欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

hdu 多校赛 Problem J. Let Sudoku Rotate

程序员文章站 2022-07-07 22:53:16
...

【题目链接】

题目意思

给你一个T,表示案例数量,给次给4*4块的数独,其中每一块数独都是4*4且不重复的,每一块数独只能顺时针反转,求使得数独合法的最少翻转次数。
hdu 多校赛 Problem J. Let Sudoku Rotate
直接暴搜加上可行性剪枝和最优性剪枝即可。
数独的限制较强,可行性剪枝的效果很好。
对每一块数独从上到下,从左到右遍历,每遍历一块,判断是否合法,若不合法就旋转一次再判断。
判断过程如下图所示,假设我们现在搜到了红色块区域,我们要对每一条蓝线和绿线查找有没有相同的元素,若有,则红色块不合法,反之,搜索下一块。
这里flag和book作为一个全局变量,flag作为标记每一次查询都是不同的,book数组标记这个数字在第几次查询中被查询到了。
hdu 多校赛 Problem J. Let Sudoku Rotate

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cctype>
using namespace std;
char s[16][16];
int w[4][4];
int ans, flag, book[16];
void rot(int x,int y)
{
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
            w[j][3 - i] = s[i + x][j + y];
    }
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
            s[i + x][j + y] = w[i][j];
    }
}
int check(int a, int b)
{
    for (int i = a; i < a + 4; i++)
    {
        flag++;
        for (int j = 0; j < b + 4; j++)
        {
            if (book[s[i][j]] == flag)
                return 0;
            book[s[i][j]] = flag;
        }
    }
    for (int j = b; j < b + 4; j++)
    {
        flag++;
        for (int i = 0; i < a + 4; i++)
        {
            if (book[s[i][j]] == flag)
                return 0;
            book[s[i][j]] = flag;
        }
    }
    return 1;
}
void dfs(int i, int j, int k)
{
    if (i == 4)
    {
        ans = min(ans, k);
        return;
    }
    if (k >= ans)
        return;
    if (j == 4)
        return dfs(i + 1, 0, k);
    for (int t = 0; t < 4; t++)
    {
        if (check(4 * i, 4 * j))
            dfs(i, j + 1, k + t);
        rot(4 * i, 4 * j);
    }
}
int main()
{
    ios::sync_with_stdio(false);
    int t;
    scanf("%d", &t);
    while (t--)
    {
        for (int i = 0; i < 16; i++)
            scanf("%s", s[i]);
        for (int i = 0; i < 16; i++)
        {
            for (int j = 0; j < 16; j++)
            {
                if (isdigit(s[i][j]))
                    s[i][j] -= '0';
                else
                    s[i][j] -= 'A' - 10;
            }
        }
        ans = 999999;
        dfs(0, 0, 0);
        printf("%d\n", ans);
    }
}