HDU 1426 Sudoku Killer
题意:
题意很简单啦。就是填数独,数独的规则是每行每列,每个3 * 3的格子必须有1-9构成且只能使用这些数字有且仅有一次
思路
dfs嘛,很明显的搜索题目,要注意的就是判断3 * 3格子的一个技巧,通过简单的四则元算就能确定数字所在的位置。保存?所在的地方到vector中,递归停止条件为填的数字已经和?的个数一样了,不用设置vis标记数组,统一通过check函数检查是否符合条件。dfs调用完成以后,如果返回false 应该把刚刚填上的数字重新设置为?,表示刚刚这种方式不行。如果返回true,则继续返回true,因为返回true当且仅当整个数独填写完成,所以一直往上回朔即可。
代码:
struct Point
{
Point(int x, int y)
: x(x), y(y) {}
int x, y;
};
char sudoku[9][9];
vector<Point>v;
bool check(int x, int y, int num)
{
for(int i = 0; i < 9; ++i)
if(num + '0' == sudoku[x][i] && i != y)
return false;
else if(num + '0' == sudoku[i][y] && i != x)
return false;
for(int i = x / 3 * 3; i < x / 3 * 3 + 3; ++i) //通过 / 3 * 3确定3 * 3格子的位置
for(int j = y / 3 * 3; j < y / 3 * 3 + 3; ++j)
if(sudoku[i][j] == num + '0' && i != x && j != y)
{
return false;
}
return true;
}
bool dfs(int pos)
{
if(pos == v.size())
{
return true;
}
for(int i = 1; i <= 9; ++i)
{
if(check(v[pos].x, v[pos].y, i))
{
sudoku[v[pos].x][v[pos].y] = i + '0'; //选上这个数字
if(dfs(pos + 1))
return true;
sudoku[v[pos].x][v[pos].y] = '?'; //放弃选的数字
}
}
return false;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif // LOCAL
bool first = true;
ios::sync_with_stdio(false); //关闭同步,加快速度
while(cin >> sudoku[0][0])
{
v.clear();
if(sudoku[0][0] == '?')
v.emplace_back(0, 0);
for(int i = 0; i < 9; ++i)
for(int j = 0; j < 9; ++j)
if(i == 0 && j == 0)
continue;
else
{
cin >> sudoku[i][j];
if(sudoku[i][j] == '?')
v.emplace_back(i, j);
}
dfs(0);
if(!first)
cout << endl;
first = false;
for(int i = 0; i < 9; ++i)
{
cout << sudoku[i][0];
for(int j = 1; j < 9; ++j)
cout << " " << sudoku[i][j];
cout << endl;
}
}
return 0;
}
一组数据(Ubuntu Sudoku游戏 中等难度随机生成的): ? ? 9 ? ? 5 2 ? ?
? 8 ? ? 9 ? 1 7 ?
4 ? ? ? ? 3 ? 6 5
? 3 ? 5 ? 2 4 9 ?
? ? ? ? 6 ? ? ? ?
? 2 7 8 ? 4 ? 5 ?
6 1 ? 3 ? ? ? ? 9
? 5 8 ? 2 ? ? 1 ?
? ? 3 6 ? ? 7 ? ?
答案:
1 6 9 7 4 5 2 8 3
3 8 5 2 9 6 1 7 4
4 7 2 1 8 3 9 6 5
8 3 6 5 1 2 4 9 7
5 4 1 9 6 7 8 3 2
9 2 7 8 3 4 6 5 1
6 1 4 3 7 8 5 2 9
7 5 8 4 2 9 3 1 6
2 9 3 6 5 1 7 4 8
GIF动态演示:(黄色表示需要填写,红色表示回朔时将数字重新设置为?)