Sudoku
题目描述:
Yi Sima was one of the best counselors of Cao Cao. He likes to play a funny game himself. It looks like the modern Sudoku, but smaller.
Actually, Yi Sima was playing it different. First of all, he tried to generate a 4×4 board with every row contains 1 to 4, every column contains 1 to 4. Also he made sure that if we cut the board into four 2×2 pieces, every piece contains 1 to 4.
Then, he removed several numbers from the board and gave it to another guy to recover it. As other counselors are not as smart as Yi Sima, Yi Sima always made sure that the board only has one way to recover.
Actually, you are seeing this because you’ve passed through to the Three-Kingdom Age. You can recover the board to make Yi Sima happy and be promoted. Go and do it!!!
Input:
The first line of the input gives the number of test cases, T(1≤T≤100). T test cases follow. Each test case starts with an empty line followed by 4 lines. Each line consist of 4 characters. Each character represents the number in the corresponding cell (one of ‘1’, ‘2’, ‘3’, ‘4’). ‘*’ represents that number was removed by Yi Sima.
It’s guaranteed that there will be exactly one way to recover the board.
Output:
For each test case, output one line containing Case #x:, where x is the test case number (starting from 1). Then output 4 lines with 4 characters each. indicate the recovered board.
Sample Input:
Sample Output:
题目描述:
这道题就是简单的缩减版的数独,从九宫格变到四宫格,要满足每一列和每一行只能填1到4,并且要满足每个数字每一列和每一行不能重复出现,并且将4宫格分成4个2V2的宫格,并且宫格里面不能重复出现1到4.
思路分析:
可以创建一个行数组和列数组来记录每行出现的数字,给他们做标记,在创建一个宫格数组,来记录宫格中出现的数字,给他们做标记,然后在从开头直接DFS,一个一个搜下去。满足要求就改变数组中的元素,并且回溯的时候不改变数组元素就行了。
代码:
#include<stdio.h>
#include<string.h>
char c1[5][5];//构造宫格
int x[5][5];//记录行元素
int y[5][5];//记录列元素
int G[5][5];//记录宫格元素
int num,flag;//flag标记宫格是否输入完,num记录*数
int m=0;
void LemonScanf()
{
int b,c,k;
for(b=0;b<4;b++)//输入宫格结构
{
scanf("%s",&c1[b]);
}
for(b=0;b<4;b++)
{
for(c=0;c<4;c++)
{
if(c1[b][c]=='*')//如果出现*,说明有一个数字要填,用num去记录
{
num++;
continue;
}
k=2*(b/2)+(c/2)+1;//这个是看在哪一个宫格。
x[b][c1[b][c]-'0']=1;//记录行元素出现的数字
y[c][c1[b][c]-'0']=1;//记录列元素出现的数字
G[k][c1[b][c]-'0']=1;//记录宫格中出现的数字
}
}
}
void LemonDFS(int x1,int y1)
{
int x2=y1/4+x1;
int y2=y1%4;
// 上面这2个,是为了一步一步的搜,因为y1+4,就x1+1,从一步一步的搜。
int i;
if(flag)//如果满足条件,就直接回溯就行了
return;
if(num==0)//如果*全没了,说明宫格已经全部输入完,可以输出
{
flag=1;
return;
}
if(c1[x2][y2]=='*')//如果*存在,就继续
{
for(i=1;i<=4;i++)
{
int k=2*(x2/2)+(y2/2)+1;
if(x[x2][i]!=1 && y[y2][i]!=1 && G[k][i]!=1)
{
G[k][i]=1;
c1[x2][y2]=i+'0';
x[x2][i]=1;
y[y2][i]=1;
//分别给行和列和宫格元素做标记,并且给数组填数字
num--;//减少*数
LemonDFS(x2,y2+1);//递归
if(flag)//这里相当于剪枝,相当于缩短时间,如果已经宫格输入完
//所以可以直接回溯就行了。
return;
c1[x2][y2]='*';
G[k][i]=0;
x[x2][i]=0;
y[y2][i]=0;
num++;//增加*数
}
}
}
else//如果不满足该元素是*,就直接进入这一步继续DFS
{
LemonDFS(x2,y2+1);
}
}
void LemonPrintf()//输出宫格中的元素
{
int b,c;
for(b=0;b<4;b++)
{
for(c=0;c<4;c++)
{
printf("%c",c1[b][c]);
}
printf("\n");
}
}
int main()
{
int b;
scanf("%d",&b);
while(b--)
{
num=0;
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
memset(G,0,sizeof(G));
flag=0;
LemonScanf();//输入宫格元素
printf("Case #%d:\n",++m);
LemonDFS(0,0);
LemonPrintf();
}
}