acm algorithm practice Jan 11 DFS
poj 2676
Description
Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure. In some of the cells are written decimal digits from 1 to 9. The other cells are empty. The goal is to fill the empty cells with decimal digits from 1 to 9, one digit per cell, in such way that in each row, in each column and in each marked 3x3 subsquare, all the digits from 1 to 9 to appear. Write a program to solve a given Sudoku-task.
![](http://poj.org/images/2676_1.jpg)
![](http://poj.org/images/2676_1.jpg)
-----------------------------------------------
a classical DFS problem search from the rear of the table.
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include <iostream>
using namespace std;
char num[9][9];
void Init()
{
int i, k;
for(i=0; i<9; i++)
{
for(k=0; k<9; k++)
{
cin >> num[i][k];
}
}
}
inline bool RowValid(int row) //检测行冲突
{
int k;
bool has[60] = {false};
for(k=0; k<9; k++)
{
if(num[row][k]!='0')
{
if(has[num[row][k]]) //in the array
return false;
else //not in the array in the array
has[num[row][k]] = true;
}
}
return true;
}
inline bool ColValid(int col) //检测列合法性
{
int i;
bool has[60] = {false};
for(i=0; i<9; i++)
{
if(num[i][col]!='0')
{
if(has[num[i][col]])
return false;
else
has[num[i][col]] = true;
}
}
return true;
}
inline bool BlockValid(int brow, int bcol) //3×3的合法行
{
int i, k;
bool has[60] = {false};
int startrow = brow * 3; //find the start row of the block
int startcol = bcol * 3; //start col of the block
for(i=startrow; i<startrow+3; i++)
{
for(k=startcol; k<startcol+3; k++)
{
if(num[i][k]!='0') //caveat 1 don't miss
{
if(has[num[i][k]])
return false;
else
has[num[i][k]] = true;
}
}
}
return true;
}
inline bool Valid(int row, int col)
{
if(!RowValid(row)) //judge the row
return false;
if(!ColValid(col)) //judge the col
return false;
if(!BlockValid(row/3, col/3)) //judge the block
return false;
return true;
}
inline bool DFS(int pos) //深搜,这样的单参数比较2个参数(行,列)方便。
{
if(-1 == pos)
return true; //DFS is finished
int row = pos / 9;
int col = pos % 9;
if(num[row][col] != '0') //the block is already filled, move to next
return DFS(pos-1);
char i;
for(i='1'; i<='9'; i++)
{
num[row][col] = i; //probe the number from 1 to 9
if(Valid(row, col)) //if it pass the judge move to the next
{
if(DFS(pos-1)) // all the sub-DFS have returned true
return true;
}
num[row][col] = '0'; //traceback
}
return false;// only when all the judges are false, actually not necessary
}
void Print()
{
int i, k;
for (i=0; i<9; i++)
{
for (k=0; k<9; k++)
{
printf("%c", num[i][k]);
}
printf("\n");
}
}
int main()
{
int cases;
scanf("%d", &cases);
while(cases--)
{
Init();
DFS(80);
Print();
}
return 0;
}
tips:
1, probe and traceback method
DFS (int n){ //which means from 1 to n blocks are done
// ........
//judge if the nth block is ok
DFS(n - 1) //which means from 1 to n-1 blocks are down
//now we can return true since nth depends on n-1th
//.......
//if the nth is not okay, trace back
}
2, u should search from the rear rather than from the head, or it will cause TLE( because of the special judge. )
3, in DFS use single parameter rather than x, y since the dfs is moving downward in order.
4, dont convert char to int, it will cost extra time and lead to TLE.
6, use int , dfs, print 3 functions to make the code clean.
obviously, it's NP problem