今天晚上抽空把数独的计算机求解也给实现了一下,由于时间有限,我这里追求的是简洁而有效的解法,故用的是最原始而直观的回溯算法。速度也还可以接受,解网上最难的数独也大概就0.0X秒的样子。最开始是一个面向过程的实现,考虑到用的是C#的实现,便把这个算法给OO化了一下。
class Sudoku
{
public int[,] Numbers { get; set; }
int x;
int y;
public Sudoku(int[,] num)
{
Numbers = num;
for (x = 0; x < 9; x++)
{
for (y = 0; y < 9; y++)
{
if (Numbers[x, y] == 0)
return;
}
}
}
public bool IsCompleted { get { return x == 9 && y == 9; } }
//计算数独,返回null表示无法计算
public Sudoku CaluSudoKu()
{
if (IsCompleted)
return this;
foreach (var num in GetAvaibleNumbers())
{
var tmpData = Numbers.Clone() as int[,];
tmpData[x, y] = num;
var sudouku = new Sudoku(tmpData);
var ret = sudouku.CaluSudoKu();
if (ret != null)
return ret;
}
return null;
}
int[] GetAvaibleNumbers()
{
var set = new HashSet<int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
for (int i = 0; i < 9; i++)
{
set.Remove(Numbers[x, i]);
set.Remove(Numbers[i, y]);
}
int xStart = x - x % 3;
int yStart = y - y % 3;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
set.Remove(Numbers[i + xStart, j + yStart]);
}
}
return set.ToArray();
}
}
算法非常简单,大概就五六十行的样子,这种简单的算法自然谈不上高效,那些讨论数独算法的时间复杂度和空间复杂度的话题不在本文讨论范围之列。