HDU 6341 Let Sudoku Rotate (DFS)
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.
题目大意:有一个16*16的数独矩阵,每个4*4的小数独矩阵每次能逆时针旋转90度,现在给出旋转后的矩阵,求出各个小矩阵最小旋转的次数和。
思路:比赛的时候看到各路大神15ms过就怂了,以为不是搜索会有规律神马的........结果...还就是单纯的搜索题。(开始自闭)。用DFS加减枝,枚举旋转次数判断旋转后行列是否满足数独的条件就行了。结果自己的出来是200+ms,,,,一想到一大堆神仙减枝到15ms就心痛.......
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<string>
using namespace std;
char s[20][20];
char p[5][5];
int vis[20];
void fun(int x,int y)//顺时针旋转矩阵90度
{
for(int i=1,a=y;i<=4;i++,a++)
{
for(int j=1,b=x;j<=4;j++,b--) p[i][j]=s[b][a];
}
for(int j=1,a=y;j<=4;j++,a++)
{
for(int i=4,b=x;i>=1;i--,b--) s[b][a]=p[i][j];
}
}
int g(char c){return (c>='0'&&c<='9')?c-'0':c-'A'+10;}
int fun1(int x)
{
for(int i=x-3;i<=x;i++)//每行不能有重复出现的数
{
memset(vis,0,sizeof vis);
for(int j=1;j<=16;j++)
{
if(vis[g(s[i][j])]!=0) return 0;
vis[g(s[i][j])]=1;
}
}
for(int j=1;j<=16;j++)//每列不能有重复出现的数
{
memset(vis,0,sizeof vis);
for(int i=1;i<=x;i++)
{
if(vis[g(s[i][j])]!=0) return 0;
vis[g(s[i][j])]=1;
}
}
return 1;
}
int s1;
void dfs(int k,int num)//k表示枚举到第k行,num表示旋转次数
{
if(num>s1) return;
if(k>16)
{
s1=min(s1,num);
return;
}
for(int a=0;a<=3;a++,fun(k,1))//枚举这4个子矩阵的旋转次数
{
for(int b=0;b<=3;b++,fun(k,5))
{
for(int c=0;c<=3;c++,fun(k,9))
{
for(int d=0;d<=3;d++,fun(k,13))
{
if(fun1(k)==0) continue;//判断前k行是否满足数独的条件
dfs(k+4,num+a+b+c+d);
}
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
for(int i=1;i<=16;i++)
scanf("%s",s[i]+1);
s1=16*3;
dfs(4,0);
printf("%d\n",s1);
}
return 0;
}
推荐阅读
-
HDU 6341 Problem J. Let Sudoku Rotate
-
HDU6341 Problem J. Let Sudoku Rotate
-
HDU 6341 Let Sudoku Rotate (DFS)
-
Hdu 6341 Problem J. Let Sudoku Rotate 暴力dfs+剪枝
-
【HDU-6341】 Let Sudoku Rotate【DFS + 剪枝】
-
HDU 6341 Let Sudoku Rotate(搜索)
-
HDU-6341:Problem J. Let Sudoku Rotate(DFS)
-
hdu 多校赛 Problem J. Let Sudoku Rotate
-
hdu6341 Problem J. Let Sudoku Rotate
-
hdu 6341 Problem J. Let Sudoku Rotate