#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#define INPUT
///#define DBG
/**
Problem: HDU2780 - Su-Su-Sudoku
Begin Time: 19th/Mar/2012 17:52
End Time: 19th/Mar/2012 20:04
Test Data: 基本上样例过了就过了
Standard output: See upstair
Knowledge Point: DFS + 回溯 + 状态是否合法判断的一个小Trick
Thought:
总体思路就是:在第5个空上挨个填一个数字,如果行的话就输出,如果不行的话回溯到上一层递归试试其他数字。直到所有数字全试完了为止
但是这里有几个小tricks
Trick1:开了一个numOfDigits数组用来记录1-9每个数字出现了几次,只有出现小于9次的数字我们才往空里填,剪枝策略1
Trick2:开了一个blockState数组,用来判断每个3x3的小数独中每个数字是否都出现过,与一个全1数组memcmp比较就可以得到结果了
不过注意blockState有一个0,所以sucBlock = {0,1,1,1...};
Trick3:对于大数独的每行/每列都放入一个数组中排序之后与sucState比较,如果是0,1,2,3,4,5,6,7,8,9则代表符合,否则不符合
Notice:我们把maze(大数独)数组的[0]行和[0]列都放弃不用了,所以要有一个前置0
Experience:
输出格式请注意!最后一行不用输出额外的换行符了,一定要仔细审题!! Presentation Error + 2
还有数组一定要记得初始化,blockState因为没初始化贡献了WA Wrong Answer + 1
*/
using namespace std;
struct node
{
int x;
int y;
};
const int sucBlock[10] = {0,1,1,1,1,1,1,1,1,1};
const int sucState[10] = {0,1,2,3,4,5,6,7,8,9};
int maze[10][10];
node unknowPoint[5];
int numOfDigits[10];
//bool isFound;
int comp(const void* a,const void* b)
{
return ( *(int*)a - *(int*)b );
}
bool checkBlock(int x,int y)
{
int blockState[10];
memset(blockState,0,sizeof(int)*10);
for(int i = x ; i < x + 3; i++)
{
for(int j = y; j < y + 3 ; j++)
{
blockState[maze[i][j]]++;
}
}
if( memcmp(blockState,sucBlock,sizeof(int)*10) != 0 )
{
return false;
}
return true;
}
bool check()
{
#ifdef DBG
printf("Debuging..Checking this maze :\n");
for(int i = 1 ; i <= 9 ; i++)
{
for(int j = 1 ; j <= 9 ; j++)
{
printf("%d ",maze[i][j]);
}
printf("\n");
}
#endif
int checkState[10];
for(int i = 1; i <= 9 ; i++)
{
///比较横行
memcpy(checkState,maze[i],sizeof(maze[i]));
qsort(checkState,10,sizeof(int),comp);
if ( memcmp(checkState,sucState,sizeof(int)*10) != 0 )
{
return false;
}
}
checkState[0] = 0;
for(int i = 1; i <= 9 ; i++)
{
///比较竖行
for(int j = 1 ; j <= 9 ; j++)
{
checkState[j] = maze[j][i];
}
qsort(checkState,10,sizeof(int),comp);
if( memcmp(checkState,sucState,sizeof(int)*10 ) != 0)
{
return false;
}
}
for(int i = 1; i <= 7 ; i = i + 3)
{
for(int j = 1; j <= 7 ; j = j + 3 )
{
if(!checkBlock(i,j))
{
return false;
}
}
}
#ifdef DBG
printf("The res is true\n");
#endif
return true;
}
bool Solve(int index)
{
if ( index > 4 )
{
return check();
}
for( int i = 1; i <= 9 ; i++)
{
if( numOfDigits[i] < 9)
{
numOfDigits[i]++;
maze[unknowPoint[index].x][unknowPoint[index].y] = i;
if ( Solve(index+1) )
{
return true;
}
maze[unknowPoint[index].x][unknowPoint[index].y] = 0;
numOfDigits[i]--;
}
}
return false;
}
int main()
{
int t,k,n;
char tmp[50];
#ifdef INPUT
freopen("b:\\acm\\hdu2780\\input.txt","r",stdin);
#ifdef DBG
freopen("b:\\acm\\hdu2780\\dbg.txt","w",stdout);
#endif
#endif
while ( scanf("%d",&t) != EOF)
{
// n = 0; //isFound = false;
// gets(tmp);
//scanf("%s",tmp);
for(k = 0 ; k < t ; k++)
{
n = 0;
memset(maze,0,sizeof(maze));
memset(tmp,0,sizeof(tmp));
memset(numOfDigits,0,sizeof(numOfDigits));
for(int i = 1 ; i <= 9 ; i++)
{
scanf("%s",tmp);
for(int j = 1; j <= 9 ; j++)
{
// scanf("%d",&maze[i][j]);
maze[i][j] = tmp[j-1] - '0';
if ( maze[i][j] == 0 )
{
unknowPoint[n].x = i;
unknowPoint[n].y = j;
n++;
}
else
{
numOfDigits[maze[i][j]]++;
}
}
}
if ( Solve(0) )
{
for(int i = 1 ; i <= 9 ; i++)
{
for(int j = 1 ; j <=9 ; j++)
{
printf("%d",maze[i][j]);
}
printf("\n");
}
}
else
{
printf("Could not complete this grid.\n");
}
if ( k != t - 1 )
{
printf("\n");
}
}
}
return 0;
}