80ms 求解世上最难数独 —— DFS的灵活运用
最近寫了好幾道DFS相關(guān)的題目,想起以前玩過的一個游戲:數(shù)獨,因為都是一個類型的思想,所以很快就想到了用 DFS來求解 數(shù)獨,此文章來教你一步一步來實現(xiàn)一個數(shù)獨模擬器 . . .
.
相關(guān)文章:
藍(lán)橋杯DFS經(jīng)典題 —— 算式900、 寒假作業(yè)(告別枚舉法)
我們需要求解的數(shù)獨就是世界上最難的數(shù)獨:
這個數(shù)獨被當(dāng)時一個 69歲的爺爺花了三天時間給算出了,有這樣一個故事:
下面我將帶大家手把手寫出這樣的一個小程序,來快速的求解出世上最難的數(shù)獨 . . .
首先,我們都知道數(shù)獨是有規(guī)則的,上面的數(shù)據(jù)不是隨便放的,規(guī)則如下:
比如下面這個情況才是允許存在的:
所以,我們需要寫一個方法,用來判斷當(dāng)前的這個數(shù)字是否允許存放在這個數(shù)獨之中,代碼如下:
bool JudgeIsNoWant(int n) // n 表示是當(dāng)前的第幾個數(shù) {int x = n / 9; // 定位當(dāng)前數(shù)的位置(數(shù)據(jù)在二維數(shù)組中的位置)int y = n % 9;for (size_t i = 0; i < 9; i++) // 橫豎 搜索{if (arr[x][i] == arr[x][y] && i != y) return false;if (arr[i][y] == arr[x][y] && i != x) return false;}// 九宮格 搜索 這里需要一個小小的算法,確定九宮格的位置for (size_t i = x / 3 * 3; i < x / 3 * 3 + 3; i++)for (size_t j = y / 3 * 3; j < y / 3 * 3 + 3; j++)if (arr[i][j] == arr[x][y] && (i != x || j != y))return false;return true; }其中的九宮格位置確定算法如下所示:
其中,這個 X 的值的位置是 (4,5),九宮格起始位置是(3,3),我們需要設(shè)計一個算法來打出這個點,而這個算法就是上面代碼上所述的:
- 4 / 3 * 3 = 3
- 5 / 3 * 3 = 3
.
下面我們就可以使用 DFS 來求解這個世上最難的數(shù)獨了,代碼如下所示:
void Dfs(int n) // 深搜思想 {// 判斷上一個數(shù)據(jù)是否滿足條件( 橫、豎、九宮格 )if (n > 0 && n <= 81) if (!JudgeIsNoWant(n - 1)) return;if (n >= 81) // 到最后則輸出數(shù)據(jù)并且返回{cout << endl << endl << "解為:" << endl << endl;for (size_t i = 0; i < 9; i++){for (size_t j = 0; j < 9; j++){ cout << arr[i][j] << " "; if (j % 3 == 2) cout << " ";}cout << endl;if (i % 3 == 2) cout << endl;}return;}int x = n / 9; // 定位當(dāng)前數(shù)的位置int y = n % 9;if (arr[x][y] != 0) // 只對 數(shù)字為 0 的元素進(jìn)行搜索Dfs(n + 1);else {// 每一個空位有 10 種可能性for (size_t i = 1; i < 10; i++) {arr[x][y] = i; // 當(dāng)前的數(shù)字放入到數(shù)組之中,Dfs(n + 1); // 進(jìn)行下一個位置的搜索arr[x][y] = 0; // 不滿足條件,重新清 0}} }這里的關(guān)鍵點在于這一行代碼:
為什么我們需要判斷上一個數(shù)字是否滿足條件呢?而不是當(dāng)數(shù)組中有了新的數(shù)據(jù)就直接判斷呢?
如果是后一種思想求解將造成很多的問題,且非常不方便,之前試過沒有成功 . . .
~
測試代碼就是讀取一個數(shù)獨,然后調(diào)用我們的 DFS方法(從 0開始):
/*世界上最難的數(shù)獨:0 0 5 3 0 0 0 0 08 0 0 0 0 0 0 2 00 7 0 0 1 0 5 0 04 0 0 0 0 5 3 0 00 1 0 0 7 0 0 0 60 0 3 2 0 0 0 8 00 6 0 5 0 0 0 0 90 0 4 0 0 0 0 3 00 0 0 0 0 9 7 0 0*/ cout << "請輸入需要求解的數(shù)獨:" << endl << endl; for (size_t i = 0; i < 9; i++) for (size_t j = 0; j < 9; j++)cin >> arr[i][j];Dfs(0); // 從第一個開始測試這個世界上最難的解為:
我們可以用如下的方式來測試一下這個 DFS 用了多少 ms :
通過大量的測試后,我們發(fā)現(xiàn)要想求出這個解就要花費 80ms 左右的時間 . . .
浪子花夢
一個有趣的程序員 ~
總結(jié)
以上是生活随笔為你收集整理的80ms 求解世上最难数独 —— DFS的灵活运用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数学建模之数据比较与影响因素分析
- 下一篇: 关于fork函数的使用