HDU 6341 Problem 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): 530    Accepted Submission(s): 146


 

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.

题意:给一个4x4为一宫一共16x16的被打乱的数独游戏,问还原至少需要多少步。

思路:直接搜索即可,乍一看似乎会爆炸,看了题解参考了大佬博客之后知道因为数独的限制性很强(每一行每一列每一宫每个数字只能出现一次)所以剪枝效果很好。分为十六个区域依次搜索,只有之前搜过的满足数独要求才继续搜。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int inf=0x3f3f3f3f;
int map[20][20],a[20][20];
int vis[20],ans;
void rt(int x,int y)//顺时针旋转
{
    int i,j,m,n;
    for(i=4*x-3,n=4*y-3;i<=4*x;i++,n++)
        for(j=4*y-3,m=4*x;j<=4*y;j++,m--)
            a[i][j]=map[m][n];
    for(i=4*x-3;i<=4*x;i++)
        for(j=4*y-3;j<=4*y;j++)
            map[i][j]=a[i][j];
}
int check(int x,int y)//剪枝,判断之前的数是否满足数独要求
{
    for(int i=4*x-3;i<4*x;i++)
    {
        memset(vis,0,sizeof(vis));
        for(int j=1;j<=4*y;j++)
        {
            if(vis[map[i][j]]) return 0;
            vis[map[i][j]]=1;
        }
    }
    for(int j=4*y-3;j<=4*y;j++)
    {
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=4*x;i++)
        {
            if(vis[map[i][j]]) return 0;
            vis[map[i][j]]=1;
        }
    }
    return 1;
}

void dfs(int x,int y,int cnt)
{
    if(x>4)
    {
        ans=min(ans,cnt);
        return ;
    }
    for(int i=0;i<4;i++)
    {
        if(i) rt(x,y);
        if(check(x,y))
        {
            if(y==4) dfs(x+1,1,cnt+i);
            else dfs(x,y+1,cnt+i);
        }
    }
    rt(x,y);//还原
}

int main()
{
    int t;
    char s;
    cin>>t;
    while(t--)
    {
        for(int i=1;i<=16;i++)
        {
            for(int j=1;j<=16;j++)
            {
                cin>>s;
                if(isdigit(s))
                    map[i][j]=s-'0';
                else map[i][j]=s-'A'+10;
            }
        }
        ans=inf;
        dfs(1,1,0);
        printf("%d\n",ans);
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值