POJ 2676 Sudoku (数独)

经典搜索问题,主要是时间上的优化,我用了三个辅助数组记录信息 row[i][k] = 1表示第i行数字k已经被使用,col[j][k] = 1表第j列数字k已经被使用,blo[i][k]表示第i个小九宫格中数字k已经被使用

还有很重要的一个优化(没有优化的话可能会超时,或者非常慢,像POJ讨论区里有很多说正着搜超时,倒着搜0ms,这的确是一个可以用的方法,但是有一定的随机性),每次填数字时,先扫描一遍整个矩阵,找出可选数字情况最少的那个0所在的地方,优先填这里,这样会使得搜索树尽可能的“瘦“一些,效果会非常明显

代码

/*
poj    2676
236K	0MS
*/ 

#include<cstdio>
#include<iostream>

#define MAXN 10
#define MAX_INT 2147483647

using namespace std;

bool flag = false;
int matrix[MAXN][MAXN], row[MAXN][MAXN], col[MAXN][MAXN], blo[MAXN][MAXN];
//用int判断比bool判断要快!
int area[MAXN][MAXN] = {
						{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
						{0, 1, 1, 1, 2, 2, 2, 3, 3, 3},
						{0, 1, 1, 1, 2, 2, 2, 3, 3, 3},
						{0, 1, 1, 1, 2, 2, 2, 3, 3, 3},
						{0, 4, 4, 4, 5, 5, 5, 6, 6, 6},
						{0, 4, 4, 4, 5, 5, 5, 6, 6, 6},
						{0, 4, 4, 4, 5, 5, 5, 6, 6, 6},
						{0, 7, 7, 7, 8, 8, 8, 9, 9, 9},
						{0, 7, 7, 7, 8, 8, 8, 9, 9, 9},
						{0, 7, 7 ,7, 8, 8, 8, 9, 9, 9}
						};

void solve(int cnt)
{
	if(flag)
		return ;
	if( !cnt )
	{
		flag = true;
		for(int i = 1;i <= 9;i ++)
		{
			for(int j = 1;j <= 9;j ++)
				cout<<matrix[i][j];
			cout<<endl;
		}
		return ;
	}
	int tx, ty, Min = MAX_INT;
	for(int i = 1;i <= 9;i ++)	//扫描矩阵,找到可选数字情况最少的那个0
	{
		for(int j = 1;j <= 9;j ++)
		{
			if( !matrix[i][j] )
			{
				int times = 0;
				for(int k = 1;k <= 9;k ++)
					if( !row[i][k] && !col[j][k] && !blo[area[i][j]][k] )
						times ++;
				if(times < Min)
				{
					Min = times ;
					tx = i;
					ty = j;
				}
			}
		}
	}
	for(int k = 1;k <= 9;k ++)
	{
		if( !row[tx][k] && !col[ty][k] && !blo[area[tx][ty]][k] )
		{
			row[tx][k] = col[ty][k] = blo[area[tx][ty]][k] = 1;
			matrix[tx][ty] = k;
			solve(cnt - 1);
			matrix[tx][ty] = 0;
			row[tx][k] = col[ty][k] = blo[area[tx][ty]][k] = 0;
		}
	}
}

int main()
{
	int cases = 0, cnt = 0;
	cin>>cases;
	while(cases --)
	{
		memset(row, 0, sizeof(row));
		memset(col, 0, sizeof(col));
		memset(blo, 0, sizeof(blo));
		memset(matrix, 0, sizeof(matrix));
		flag = false;
		cnt = 0;
		for(int i = 1;i <= 9;i ++)
		{
			for(int j = 1;j <= 9;j ++)
			{
				char ch;
				cin>>ch;
				matrix[i][j] = ch - '0';
				row[i][matrix[i][j]] = 1;
				col[j][matrix[i][j]] = 1;
				blo[area[i][j]][matrix[i][j]] = 1;
				if( !matrix[i][j] )
					cnt ++;
			}
		}
		solve(cnt);
	}
	return 0;
}

POJ 2676 Sudoku (数独)

时间: 2024-11-03 03:42:47

POJ 2676 Sudoku (数独)的相关文章

POJ 2676 Sudoku (数独 DFS)

Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14368   Accepted: 7102   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

ACM : POJ 2676 SudoKu DFS - 数独

SudoKu Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu 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 c

poj 2676 Sudoku (dfs)

链接:poj 2676 题意:给定一个未完成的数独,0是待填位置,其他均为已填入的数字.如果能将其 补充完整,则输出补充完整的数独(有多组答案输出任意一组),否则原样输出 数独:一个9行9列的网格,包括9个3*3的子网格,要求每行.每列.每个子网格内 都只能使用一次1-9中的一个数字, 即每行.每列.每个子网格内都不允许出现相同的数字. 分析:对于每一个未填的格,依次判断它所在行.列.子网格是否填了1-9, 若都未填,先填上该值,继续搜索, 若无法填写了,再回溯,填上其他可能的值,继续搜索 看别

POJ 2676 Sudoku (搜索,Dancing Links)

题目: http://poj.org/problem?id=2676 题意: 数独,每行1-9,每列1-9,每3*3小格1-9,填数,不能重复 方法:Dancing Links(16ms)或者DFS暴搜(400-900ms) Dancing Links(DLX) 是为了解决矩阵精确覆盖问题的算法,算法效率非常高 使用DLX解决的问题必须转化为矩阵精确覆盖问题: 1.DLX详解: http://wenku.baidu.com/view/d8f13dc45fbfc77da269b126.html 2

POJ 2676 - Sudoku(数独)

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2676 题目大意: 给出一个数字n,表示有n组数据. 每组数据包括一个n*n的数独,0表示未填的数字.数字之间没有空格. 输出填好的数独,使得每行.每列.每个九宫格中的数字都不重复. 分析: 经典搜索题目. 数组一定要开大一点,数组一定要开大一点,数组一定要开大一点. AC代码: 1 #include<cstdio> 2 #include<algorith

搜索 --- 数独求解 POJ 2676 Sudoku

Sudoku Problem's Link:   http://poj.org/problem?id=2676 Mean: 略 analyse: 记录所有空位置,判断当前空位置是否可以填某个数,然后直接DFS,注意从后往前搜索,时间比正向搜快很多.16ms水过 Time complexity: O(n) Source code:  // Memory Time // 1347K 0MS // by : crazyacking // 2015-04-10-14.30 #include<map>

poj 2676 Sudoku (基础DFS)

Sudoku Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15456   Accepted: 7574   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.

POJ 2676 Sudoku

题目链接:http://poj.org/problem?id=2676 数独问题.用dancing links解决. 建图参考 http://wenku.baidu.com/link?url=3Tk5gVYew3mSQ2f2LxDODxPg3v-yqJPUaEkuZpfkHTxfSPQuM_n8TGl2Swp68XQY9MYN2BENZ-pmv9dpoh3Ulqt1lT-ZNo90jcJyi1eXasm 要注意的就是搜索的时候 要先搜索 那一列中节点最少的,否则时间会很长. 1 #include

Poj 2676 Sudoku[dfs]

题目大意: 九宫格问题,也有人叫数独问题 把一个9行9列的网格,再细分为9个3*3的子网格,要求每行.每列.每个子网格内都只能使用一次1~9中的一个数字,即每行.每列.每个子网格内都不允许出现相同的数字. 0是待填位置,其他均为已填入的数字. 要求填完九宫格并输出(如果有多种结果,则只需输出其中一种) 如果给定的九宫格无法按要求填出来,则输出原来所输入的未填的九宫格 思路: DFS 深搜 char map[10][10];/*数据存储*/bool row[10][10];/*行存在数*/bool