Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1426
一道可以用Dfs解决的题目。思路并不难,只要一个一个数字试就行了。
但很奇怪,我试图每次挑最可能的数字进行搜索,结果错了。后来直接搜索,没有考虑最有可能的数字,反而还对了。
估计我功力还不够深厚。
代码反复修改,虽然能AC,但代码的可读性有点降低。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 9+3;
const int LENGTH = 9;
const int COUNTPOS = 12;
// the first param means it's in the ith row or column or rec, the second param means the exact num
int visRow[ MAXN ][ MAXN ]; // the row nums
int visCol[ MAXN ][ MAXN ]; // the colomn nums
int visRec[ MAXN ][ MAXN ][ MAXN ]; // the rectangle nums
const int EXIST = 1;
const int NOTEXSIT = 0;
const int UNKNOW = -1;
int sudoku[MAXN][MAXN];
int counter = 0;
inline int CharToInt( int c ) {
if( c=='?' ) {
return UNKNOW;
} else {
return c-'0';
}
}
void PrintSudoKu( ) {
int i, j;
for( i=0; i<9; i++ ) {
printf( "%d", sudoku[i][0] );
for( j=1; j<9; j++ ) {
printf( " %d", sudoku[i][j] );
}
printf("\n");
}
}
void MakeVis() {
memset( visCol, NOTEXSIT, sizeof(visCol) );
memset( visRow, NOTEXSIT, sizeof(visRow) );
memset( visRec, NOTEXSIT, sizeof(visRec) );
int i, j;
for( i=0; i<LENGTH; i++ ) {
for( j=0; j<LENGTH; j++ ) {
if( sudoku[i][j] != UNKNOW ) {
visRow[i][ sudoku[i][j] ] = EXIST;
visRow[i][ COUNTPOS ] ++;
visCol[j][ sudoku[i][j] ] = EXIST;
visCol[j][ COUNTPOS ] ++;
visRec[ i/3 ][ j/3 ][ sudoku[i][j] ] = EXIST;
visRec[ i/3 ][ j/3 ][ COUNTPOS ] ++;
counter ++;
}
}
}
}
void GetPos( int *x, int *y );
void Dfs( int x, int y );
int main()
{
char c;
int konghang = 0;
while( cin >> c ) {
sudoku[0][0] = CharToInt(c);
if( konghang != 0 ) {
cout << endl;
}
konghang = 1;
int i, j;
for( i=1; i<9; i++ ) {
cin >> c;
sudoku[0][i] = CharToInt( c );
}
for( i=1; i<9; i++ ) {
//getchar();
cin >> c;
sudoku[i][0] = CharToInt( c );
for( j=1; j<9; j++ ) {
cin >> c;
sudoku[i][j] = CharToInt( c );
}
}
counter = 0;
MakeVis();
int x ,y;
GetPos( &x, &y );
Dfs( x, y );
PrintSudoKu();
}
return 0;
}
void GetPos( int *x, int *y ) {
/*int i, temp = -1;
for( i=0; i<LENGTH; i++ ) {
if( temp<visRow[i][COUNTPOS] && visRow[i][COUNTPOS]!=LENGTH ) {
temp = visRow[i][COUNTPOS];
*x = i;
}
}
for( i=*x; i<LENGTH; i++ ) {
if( sudoku[*x][i]==UNKNOW ) {
*y = i;
return ;
}
}*/
for( int i=0; i<9;i++ ) {
for( int j=0; j<9; j++ ) {
if( sudoku[i][j]==UNKNOW ) {
*x = i;
*y = j;
return ;
}
}
}
}
void GetDfsPos( int x, int y, int *tempx, int *tempy );
void Dfs( int x, int y ) {
if( counter == LENGTH*LENGTH ) {
return ;
}
int vis[10] = {0};
// which num isn't used
int i;
for( i=1; i<=9; i++ ) {
if( visCol[y][i]!=NOTEXSIT ) vis[ i ] ++;
if( visRow[x][i]!=NOTEXSIT ) vis[ i ] ++;
if( visRec[x/3][y/3][i]!=NOTEXSIT ) vis[ i ] ++;
}
for( i=1; i<=9; i++ ) {
if( vis[ i ]==0 ) {
sudoku[x][y] = i;
visCol[y][i] = EXIST; visRow[x][i] = EXIST; visRec[x/3][y/3][i] = EXIST;
//visCol[y][COUNTPOS] ++; visRow[x][COUNTPOS] ++; visRec[x/3][y/3][COUNTPOS] ++;
counter ++;
int tempx, tempy;
GetDfsPos( x, y, &tempx, &tempy );
Dfs( tempx, tempy );
if( counter == 81 ) {
return ;
}
counter --;
visCol[y][i] = NOTEXSIT; visRow[x][i] = NOTEXSIT; visRec[x/3][y/3][i] = NOTEXSIT;
//visCol[y][COUNTPOS] --; visRow[x][COUNTPOS] --; visRec[x/3][y/3][COUNTPOS] --;
sudoku[x][y] = UNKNOW;
}
}
}
void GetDfsPos( int x, int y, int *tempx, int *tempy ) {
/*int tempCol = visCol[y][COUNTPOS]==9 ? -1 : visCol[y][COUNTPOS],
tempRow = visRow[x][COUNTPOS]==9 ? -1 : visRow[x][COUNTPOS],
tempRec = visRec[x/3][y/3][COUNTPOS]==9 ? -1 : visRec[x/3][y/3][COUNTPOS];
if( tempCol>=tempRow && tempCol>=tempRec ) {
for( int i=0; i<9; i++ ) {
if( sudoku[i][y]==UNKNOW ) {
*tempx = i; *tempy = y; return ;
}
}
}
if( tempRow>=tempCol && tempRow>=tempRec ) {
for( int i=0; i<9; i++ ) {
if( sudoku[x][i]==UNKNOW ) {
*tempx = x; *tempy = i; return ;
}
}
}
for( int i= (x/3)*3; i<=(x/3)*3+2; i++ ) {
for( int j= (y/3)*3; j<=(y/3)*3+2; j++ ) {
if( sudoku[i][j]==UNKNOW ) {
*tempx = i; *tempy = j; return ;
}
}
}*/
for( int i=0; i<9;i++ ) {
for( int j=0; j<9; j++ ) {
if( sudoku[i][j]==UNKNOW ) {
*tempx = i;
*tempy = j;
return ;
}
}
}
}