题目链接:http://poj.org/problem?id=2676,不过交了之后才发现,POJ目前停服状态。。。。。但是算法是对的,在牛客网上找了一题数独。
刚看到这一题不是很明白要怎么做,百度找了,大家都是写DFS,扔个代码什么也没说。
写完我觉得:这题最重要的思想不是DFS,是回溯。DFS应该是辅助算法。
解题思想 (大力出奇迹):
1. 依次在空格里面填上“1~9”,并检查这个数字是否合法(其所在的行、列,以及3X3的子区域里不存在重复的数字)。如果合法,则前进到下一个格子。
2. 如果在某个格子里,从“1”到“9”都不合法,这说明前面某个格子填错了。这时就回退到上一格,继续试。例如,如果上一格已填的数字是3,就继续试4,5,6,… 是否合法。如果找到一个合法的数字,则又前进到下一格。如果找不到,说明前面还有格子也填错了,则继续回退到更前面一格,… 如此反复。
4. 如果这个数独是有解的,我们总会遇到“蒙对了”的情况。如果这个数独是没有解的,那么我们会遇到“第一个格子试了1~9所有的数字都不行”的情况。
#include <iostream> using namespace std; int M[9][9]; bool flag = false; int check(int row, int column, int x) { for (int i = 0; i < 9; i++) { if (M[i][column] == x || M[row][i] == x) return 0; } int r = row / 3 * 3, c = column / 3 * 3; for (int i = r; i < r + 3; i++) { for (int j = c; j < c + 3; j++) { if (M[i][j] == x) return 0; } } return 1; } void DFS(int row, int column) { if (row == 9) { flag = true; return; } if (M[row][column] == 0) { int i; for (i = 1; i <= 9; i++) { if (check(row, column, i)) { M[row][column] = i; DFS(row + (column + 1) / 9, (column + 1) % 9); if (flag) return; } } if (i == 10) { //这里回溯,赋值0是为了下次继续赋值 M[row][column] = 0; return; } } //DFS((row + 1) % 9, column+(row+1)/9); DFS(row + (column + 1) / 9, (column + 1) % 9); } int main() { int i = 1; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { cin >> M[i][j]; } } DFS(0, 0); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { cout << M[i][j] << " "; } cout << endl; } return 0; }