1. 程式人生 > >隨手練—— 數獨 POJ - 5547 (回溯法+DFS)

隨手練—— 數獨 POJ - 5547 (回溯法+DFS)

pan lse 個數字 blank 存在 網上 pre 說明 strong

題目鏈接: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; }

隨手練—— 數獨 POJ - 5547 (回溯法+DFS)