POJ 2676 Sudoku [暴搜]

题意:
给定一个9*9矩阵,矩阵值只为0到9;0代表需要你去填充的格子。只能用1到9中的数字填充。
问怎样填充可以满足三个约束条件,分别是:横看,竖看,3*3方格看,都刚好是1到9各个数字不重复。
思路:
暴搜。看了discuss以为很复杂。其实不会。
不过就是需要用
bool row[N][N];
bool col[N][N];
bool sqr[N][N];
三个哈希数组来判断每行,每列,每个3*3方格里面是否可以放某个数字。否则应该会超时。
反正我发现这种题目挺有意思的。看似很复杂很奇妙的要求,其实是可以直接暴力搜到。

#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<cmath>
#include<algorithm>
#define llong long long
#define Min(a,b) (a<b?a:b)
#define Max(a,b) (a>b?a:b)
#define Abs(a) ((a)>0?(a):-(a))
#define Mod(a,b) (((a)-1+(b))%(b)+1)
using namespace std;
int n,m;
const int N=15;
const int inf=99999999;
char a[N][N];
bool row[N][N];
bool col[N][N];
bool sqr[N][N];
#define Func(a,b) ((a-1)/3+1+(b-1)/3*3)
bool JudgeCan(int i,int j,int k)
{
	return (row[i][k]&&col[j][k]&&sqr[(j-1)/3+1+(i-1)/3*3][k]);
	
}
void SetCan(int i,int j,int k,int w)
{
	row[i][k]=w;
	col[j][k]=w;
	sqr[(j-1)/3+1+(i-1)/3*3][k]=w;//3*3的方格有9个。
}
void findnext(int &i ,int &j)
{
	while(a[i][j])
	{
		if(i>9)
			break;
		if(j==9)
		{
			j=1;
			i++;
		}
		else
		{
			j++;
		}
	}
}
bool dfs(int i,int j)
{
	int ii=i,jj=j;
	if(i>9)
		return true;
	for(int k=1;k<=9;k++)
	{
		if(JudgeCan(ii,jj,k))
		{
			a[ii][jj]=k;
			SetCan(ii,jj,k,0);
			findnext(i,j);
			if(dfs(i,j))
			{
				return true;
			}
			else
			{
				a[ii][jj]=0;
				SetCan(ii,jj,k,1);
			}
		}
	}
	return false;
}
void solve()
{
	memset(row,0xff,sizeof(row));
	memset(col,0xff,sizeof(col));
	memset(sqr,0xff,sizeof(sqr));
	for(int i=1;i<=9;i++)
		for(int j=1;j<=9;j++)
		{
			if(a[i][j])
			{
				SetCan(i,j,a[i][j],0);
			}
		}
	int i=1,j=1;
	findnext(i,j);
	dfs(i,j);
	for(int i=1;i<=9;i++)
	{
		for(int j=1;j<=9;j++)
		{
			printf("%d",a[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		memset(a,0,sizeof(a));
		for(int i=1;i<=9;i++)
		{
			scanf("%s",a[i]+1);
			for(int j=1;j<=9;j++)
				a[i][j]-='0';//将字符型处理成数值型
		}
		solve();
	}
	return 0;
}


你可能感兴趣的:(POJ 2676 Sudoku [暴搜])