Sudoku
Posted rign
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Sudoku相关的知识,希望对你有一定的参考价值。
题目来源:POJ 3074 Sudokuhttp://poj.org/problem?id=3074
In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example,Given some of the numbers in the grid, your goal is to determine the remaining numbers such that the numbers 1 through 9 appear exactly once in (1) each of nine 3 × 3 subgrids, (2) each of the nine rows, and (3) each of the nine columns.The input test file will contain multiple cases. Each test case consists of a single line containing 81 characters, which represent the 81 squares of the Sudoku grid, given one row at a time. Each character is either a digit (from 1 to 9) or a period (used to indicate an unfilled square). You may assume that each puzzle in the input will have exactly one solution. The end-of-file is denoted by a single line containing the word “end”.
这道题目是关于搜索的一道题目,首先我们来分析一下题意(9cdot9)的方格中,可以填入1-9,但是每行每列每个9宫格不准有重复的数字于是我们可以尝试每个可以填入格子的位置去深度搜索,但是这个样子就会产生无效的搜索,比如两次不同搜索在填入了相同的数字,只是因为搜索的顺序不同,所以我们要去确定搜索的顺序,防止产生重复的搜索,其次就是,我们不一定需要把1-9每个数字都尝试一遍,因为题目中所给的已知,可以确定未知的位置所能搜索的数字,再者就是关于搜索的状态优化,可以利用二进制可以来优化状态
搜索主体
bool dfs(int now) {
if (now == 0) return 1;
int temp = 10, x, y;
for (int i = 0; i < 9; i++)//确定搜索顺序,找寻可以填数字量最少的位置
for (int j = 0; j < 9; j++) {
if (str[i][j] != '.') continue;
int val = row[i] & col[j] & grid[g(i, j)];
if (!val) return 0;
if (cnt[val] < temp) {
temp = cnt[val];
x = i, y = j;
}
}
int val = row[x] & col[y] & grid[g(x, y)];//确定该位置可以填的数字
for (; val; val -= val&-val) {
int z = num[val&-val];//num是一个二进制和该数字的映射
str[x][y] = '1' + z;
flip(x, y, z);
if (dfs(now - 1)) return 1;//遍历,利用return提前终止
flip(x, y, z);
str[x][y] = '.';
}
return 0;
}
填入数字时关于某位置的行列格子的数字二进制反转操作
inline int g(int x, int y) {
return ((x / 3) * 3) + (y / 3);//确定格子
}
inline void flip(int x, int y, int z) {
//反转
row[x] ^= 1 << z;
col[y] ^= 1 << z;
grid[g(x, y)] ^= 1 << z;
}
预处理
for (int i = 0; i < 1 << 9; i++)
for (int j = i; j; j -= j&-j) cnt[i]++;
for (int i = 0; i < 9; i++)
num[1 << i] = i;
for (int i = 0; i < 9; i++) row[i] = col[i] = grid[i] = (1 << 9) - 1;
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
if (str[i][j] != '.') flip(i, j, str[i][j] - '1');
else tot++;
dfs(tot);
以上是关于Sudoku的主要内容,如果未能解决你的问题,请参考以下文章
洛谷OJ 1074 靶型sudoku dfs(搜索顺序优化)