代码改变世界

poj 2676 sudoku ( 数独)----DFS

2012-03-07 19:20  java环境变量  阅读(292)  评论(0编辑  收藏  举报

 

                                         Sudoku
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 9664   Accepted: 4786   Special Judge

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.

Input

The input data will start with the number of the test cases. For each test case, 9 lines follow, corresponding to the rows of the table. On each line a string of exactly 9 decimal digits is given, corresponding to the cells in this line. If a cell is empty it is represented by 0.

Output

For each test case your program should print the solution in the same format as the input data. The empty cells have to be filled according to the rules. If solutions is not unique, then the program may print any one of them.

Sample Input

1
103000509
002109400
000704000
300502006
060000050
700803004
000401000
009205800
804000107

Sample Output

143628579
572139468
986754231
391542786
468917352
725863914
237481695
619275843
854396127

 

 

/*
     只能说可能是poj的测试数据太诡异。。
	 我从第一个开始搜的代码 交的结果
	 Memory: 164 KB   Time: 1422 MS  
     Language: C++   Result: Accepted  

     然后看了下poj关于此题的Dicuss。。。看到说倒着搜可以缩时间。
	 结果是  16MS....  无语了。

  这道题我是直接DFS。  所以时间用了1422MS。
  下面是倒着搜的代码。
*/

//Memory: 164 KB   Time: 16 MS  
//Language: C++   Result: Accepted  

#include<stdio.h>
#include<string.h>
const int MAX=9;
int dfs(int m,int count); //DFS搜索
int judge(int x,int y,char t); //判断是否可以放数字t
char gird[MAX][MAX],vir[MAX*MAX];
int tot;
int main()
{
	//freopen("1.txt","r",stdin);
	int n;
	int i,j;
	while(scanf("%d",&n)!=EOF)
	{
		while(n--)
		{
			tot=0;
		    memset(vir,0,sizeof(vir));
		   for(i=0;i<MAX;i++)
		   {
		    	scanf("%s",gird[i]);
		     	for(j=0;j<MAX;j++)
				if(gird[i][j]=='0') tot++;  //统计需要填的格子数
		   }
	    	dfs(80,0);  //倒着搜 效果很神奇。。。
	    	printf("\n");
		}
	}
	return 0;
}
int dfs(int m,int count)
{
	int i,j;
	int x=m/MAX,y=m%MAX;
	if(count==tot)   //如果全部格子都填满 并不冲突 打印结果
	{
		for(i=0;i<MAX;i++)
		{
			for(j=0;j<MAX;j++)
				printf("%c",gird[i][j]);
		printf("\n");
		}
		return 1;
	}
	if(gird[x][y]=='0'&&!vir[m])  //判断是否是空的格子
	{
		for(i=1;i<10;i++)
		{
		   if(judge(x,y,'0'+i))   //判断尝试的数字i 是否与已有的数冲突
		   {
			   vir[m]=1;
			   gird[x][y]='0'+i;
			   if(!dfs(m-1,count+1))  //满足则 继续深搜
			   {
				   vir[m]=0;       //如果尝试失败 记得复原
			    gird[x][y]='0';
			   }
			   else return 1;
		   }
		}
	}
	else if(dfs(m-1,count)) return 1; //如果不是 则搜索下一个
	return 0;
}
int judge(int x,int y,char t)
{
	int i,j;
	for(i=0;i<MAX;i++)   //判断行列是否冲突
		if(gird[x][i]==t||gird[i][y]==t)
			return 0;
	int tempx=(x/3)*3,tempy=(y/3)*3;
	for(i=tempx;i<tempx+3;i++)    //判段九个小格子是否冲突
		for(j=tempy;j<tempy+3;j++)
			if(gird[i][j]==t) return 0;
	return 1;
}