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. 
-----------------------------------------------
a classical DFS problem search from the rear of the table.  
代码
#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 

posted @ 2011-01-12 12:27  love && peace  阅读(248)  评论(0编辑  收藏  举报