數獨求解(Sudoku) C++版

文章做者:姜南(Slyar) 文章來源:Slyar Home (www.slyar.com) 轉載請註明,謝謝合做。html

今天翻手機裏的遊戲時,找到了之前常常玩的九宮格,也就是數獨。拼出一個20個已知數字的數獨後,我又想寫代碼解數獨了...ios

思路比較清晰,依舊是DFS,感受應該不難寫。花了2個小時搞定代碼,用手機裏的數獨遊戲測試了幾回,所有經過...函數

意外發現PKU 2676就是數獨求解,用我寫的代碼交了2次全是TLE...看了Discuss之後得知要AC必須從後面開始搜...囧,數據問題,數據問題...測試

恩,代碼的註釋我寫的異常清楚,就再也不寫廢話了。spa

注:這個代碼是我本身玩的,不是pku 2676的AC代碼。code

#include <iostream>

using namespace std;

/* 構造完成標誌 */
bool sign = false;

/* 建立數獨矩陣 */
int num[9][9];

/* 函數聲明 */
void Input();
void Output();
bool Check(int n, int key);
int DFS(int n);

/* 主函數 */
int main()
{
    cout << "請輸入一個9*9的數獨矩陣,空位以0表示:" << endl;
    Input();
    DFS(0);
    Output();
    system("pause");
}

/* 讀入數獨矩陣 */
void Input()
{
    char temp[9][9];
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            cin >> temp[i][j];
            num[i][j] = temp[i][j] - '0';
        }
    }
}

/* 輸出數獨矩陣 */
void Output()
{
    cout << endl;
    for (int i = 0; i < 9; i++)
    {
        for (int j = 0; j < 9; j++)
        {
            cout << num[i][j] << " ";
            if (j % 3 == 2)
            {
                cout << "   ";
            }
        }
        cout << endl;
        if (i % 3 == 2)
        {
            cout << endl;
        }
    }
}

/* 判斷key填入n時是否知足條件 */
bool Check(int n, int key)
{
    /* 判斷n所在橫列是否合法 */
    for (int i = 0; i < 9; i++)
    {
        /* j爲n豎座標 */
        int j = n / 9;
        if (num[j][i] == key) return false;
    }
    
    /* 判斷n所在豎列是否合法 */
    for (int i = 0; i < 9; i++)
    {
        /* j爲n橫座標 */
        int j = n % 9;
        if (num[i][j] == key) return false;
    }
    
    /* x爲n所在的小九宮格左頂點豎座標 */
    int x = n / 9 / 3 * 3;
    
    /* y爲n所在的小九宮格左頂點橫座標 */
    int y = n % 9 / 3 * 3;
    
    /* 判斷n所在的小九宮格是否合法 */
    for (int i = x; i < x + 3; i++)
    {
        for (int j = y; j < y + 3; j++)
        {
            if (num[i][j] == key) return false;
        }
    }
    
    /* 所有合法,返回正確 */
    return true;
}

/* 深搜構造數獨 */
int DFS(int n)
{
    /* 全部的都符合,退出遞歸 */
    if (n > 80)
    {
        sign = true;
        return 0;
    }
    /* 當前位不爲空時跳過 */
    if (num[n/9][n%9] != 0)
    {
        DFS(n+1);
    }
    else
    {
        /* 不然對當前位進行枚舉測試 */
        for (int i = 1; i <= 9; i++)
        {
            /* 知足條件時填入數字 */
            if (Check(n, i) == true)
            {
                num[n/9][n%9] = i;
                /* 繼續搜索 */
                DFS(n+1);
                /* 返回時若是構形成功,則直接退出 */
                if (sign == true) return 0;
                /* 若是構造不成功,還原當前位 */
                num[n/9][n%9] = 0;
            }
        }
    }
}

Sample Inputhtm

103000509
002109400
000704000
300502006
060000050
700803004
000401000
009205800
804000107blog

Sample Output遞歸

143628579
572139468
986754231
391542786
468917352
725863914
237481695
619275843
854396127遊戲

轉載請註明:Slyar Home » 數獨求解(Sudoku) C++版

相關文章
相關標籤/搜索