HDU - 5547 数独(回溯法)
题目链接:HDU-5547 http://acm.hdu.edu.cn/showproblem.php?pid=5547
正所谓:骗分过样例,暴力出奇迹。
解题思想(暴力出奇迹(DFS+回溯)):
1. 依次在空格里面填上“1~9”,并检查这个数字是否合法(其所在的行、列,以及3X3的子区域里不存在重复的数字)。如果合法,则前进到下一个格子。
2. 如果在某个格子里,从“1”到“9”都不合法,这说明前面某个格子填错了。这时就回退到上一格,继续试。例如,如果上一格已填的数字是3,就继续试4,5,6,… 是否合法。如果找到一个合法的数字,则又前进到下一格。如果找不到,说明前面还有格子也填错了,则继续回退到更前面一格,… 如此反复。
4. 如果这个数独是有解的,我们总会遇到“蒙对了”的情况。
HDU 的这题实在是太坑了,题目描述里有一句:Each test case starts with an empty line followed by 4 lines,没仔细看输入样例里也没有空行 。66666666666666666。告辞,我错了。
#include <iostream> #include <string> using namespace std; int M[4][4]; bool flag = false; int check(int row, int column, int x) { for (int i = 0; i < 4; i++) { if (M[i][column] == x || M[row][i] == x) return 0; } int r = row / 2 * 2, c = column / 2 * 2; for (int i = r; i < r + 2; i++) { for (int j = c; j < c + 2; j++) { if (M[i][j] == x) return 0; } } return 1; } void DFS(int row, int column) { if (row == 4) { flag = true; return; } if (M[row][column] == -6) { int i; for (i = 1; i <= 4; i++) { if (check(row, column, i)) { M[row][column] = i; DFS(row + (column + 1) / 4, (column + 1) % 4); if (flag) return; } } if (i == 5) { M[row][column] = -6; return; } } DFS(row + (column + 1) / 4, (column + 1) % 4); } int main() { int i = 1,n; cin >> n; string s; cin.ignore(); while (n--) { flag = false; for (int i = 0; i < 4; i++) { getline(cin, s); if (s.empty()) { i--; continue; } for (int j = 0; j < 4; j++) { M[i][j] = s[j]-'0'; } } DFS(0, 0); cout << "Case #" << i++ << ":" << endl; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { cout << M[i][j]; } cout << endl; } } return 0; }