// 356K 16MS G++
#include <cstdio>
#include <queue>
#include <cstring>
#define MAX 9
using namespace std;
char initBoard[MAX][MAX];
int initFIlledNum;
void printBoard(char board[MAX][MAX]) {
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
printf("%c", board[j][i] + '0');
}
printf("\n");
}
}
char DFS(int beginX, int beginY, int filledNum) {
if (filledNum == 81) {
printBoard(initBoard);
return 1;
}
int nextFillx = 0;
int nextFilly = 0;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (initBoard[i][j] == 0) {
nextFillx = i;
nextFilly = j;
break;
}
}
}
int rowNumMap[10] = {0};
int columnNumMap[10] = {0};
for (int i = 0; i < 9; i++) {
int val1 = initBoard[i][nextFilly]; // check the row
int val2 = initBoard[nextFillx][i]; // check the column
if (val1 > 0) {
rowNumMap[val1] = 1;
}
if (val2 > 0) {
columnNumMap[val2] = 1;
}
}
int matrixMap[10] = {0};
int matrixBeginX = (nextFillx/3) * 3;
int matrixBeginY = (nextFilly/3) * 3;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int val = initBoard[matrixBeginX + i][matrixBeginY + j];
if (val > 0) {
matrixMap[val] = 1;
}
}
}
for (int i = 1; i < 10; i++) { // try fill some num
if (!rowNumMap[i] && !columnNumMap[i] && !matrixMap[i]) {// if both the row and the column do not appear this num
initBoard[nextFillx][nextFilly] = i;
if (DFS(nextFillx, nextFilly, filledNum +1)) {
return 1;
}
initBoard[nextFillx][nextFilly] = 0;
}
}
return 0;
}
void solve() {
// printBoard(initBoard);
if (initFIlledNum == 81) {
printBoard(initBoard);
return;
}
DFS(0,0, initFIlledNum);
}
int main() {
int caseNum;
scanf("%d", &caseNum);
for (int i = 0; i < caseNum; i++) {
initFIlledNum = 0;
for (int j = 0; j < MAX; j++) {
char line[10];
scanf("%s", line);
for (int k = 0; k < MAX; k++) {
initBoard[k][j] = line[k] - '0';
if (initBoard[k][j] != 0) {
initFIlledNum++;
}
}
}
solve();
}
}
经典的DFS题,顺带考察剪枝,一开始BFS习惯了,结果直接TLE,想想也是,这种只要求出一种答案就可以的题,DFS是第一选, BFS在这种情况下铺的大了点.
题最开始也没审清,光注意到每行每列不能有重复数字,没有注意到还要求3*3小矩阵也不能有重复的,WA了一次。
本身没啥可说的,这种DFS连checkFlag也不需要, 因为每次都一定是不同的局面(每次位置都不一样),每次DFS都从矩阵中找到第一个为0的空位,然后结合
行,列和3*3矩阵来决定可以在此位置填哪些值,继续DFS即可,每次DFS还要传递此轮DFS已经填好了多少个数字,当填够了9*9个以后,就可以打印矩阵并返回1了,
一开始在输入上面栽个跟头,因为数字是挨着的,所以%d不行,用%c,但是%c会把回车也算计来,后来就直接%s读每行然后挨个处理了,在输入时就统计初始的矩阵填好了多少个数字,如果给的是都填好的,直接返回就OK。