也是一个简单剪枝的dfs。记录所有为0的位置,依次填写,当发现某个空格可选的填写数字已经没有时,说明该支路无效,剪掉。
不算是一个难题吧,但是还是花了不少时间,问题主要出在细节上,行列坐标反了、3乘3小格的位置判断等。写程序一定要细心。
#include <iostream> using namespace std; const int MAX_R = 9; int map[MAX_R + 1][MAX_R + 1]; int zero_pos[MAX_R * MAX_R][2]; int possible_digits[MAX_R * MAX_R][9]; int zero_cnt; int setPossibleDigits(int x, int y, int s) { bool possible[10]; memset(possible, 0, sizeof(possible)); for (int i = 1; i <= MAX_R; i++){ possible[map[i][x]] = true; possible[map[y][i]] = true; } int subX = (x - 1) / 3; int subY = (y - 1) / 3; for (int i = subX * 3 + 1; i <= subX * 3 + 3; i++){ for (int j = subY * 3 + 1; j <= subY * 3 + 3; j++){ possible[map[j][i]] = true; } } int cnt = 0; for (int i = 1; i <= 9; i++){ if (!possible[i]) possible_digits[s][cnt++] = i; } return cnt; } bool dfs(int step) { if (step == zero_cnt){ return true; } int curX = zero_pos[step][1], curY = zero_pos[step][0]; int possible_cnt = setPossibleDigits(curX, curY, step); if (possible_cnt == 0){ return false; } for (int i = 0; i < possible_cnt; i++){ map[curY][curX] = possible_digits[step][i]; if (dfs(step + 1)) return true; else map[curY][curX] = 0; } return false; } int main() { int t; cin >> t; while (t--){ memset(map, 0, sizeof(map)); memset(zero_pos, 0, sizeof(zero_pos)); memset(possible_digits, 0, sizeof(possible_digits)); zero_cnt = 0; for (int i = 1; i <= MAX_R; i++){ for (int j = 1; j <= MAX_R; j++){ char ch; cin >> ch; map[i][j] = ch - '0'; if (map[i][j] == 0){ zero_pos[zero_cnt][0] = i; zero_pos[zero_cnt++][1] = j; } } } dfs(0); for (int i = 1; i <= MAX_R; i++){ for (int j = 1; j <= MAX_R; j++){ cout << map[i][j]; } cout << endl; } } return 0; }