另一個數獨求解c++程式
來自這裡,他用多種語言實現了同一種方法。包括c++、python、cs等。
#include <iostream> #include <queue> #include <string> #include <vector> using namespace std; typedef int coord; typedef int block; enum view { GRD, ROW, COL, BOX }; const int VIEW = 4; const int UNIT = 3; const int SIZE = UNIT * UNIT; const int COORD = SIZE * SIZE * SIZE; const int BLOCK = VIEW * SIZE * SIZE; const int DEFINED = 0xDEF; const string DIGITS = "123456789"; inline coord coord_of(int i, int j, int k) { return (i * SIZE + j) * SIZE + k; } inline block block_of(view v, int p, int q) { return (v * SIZE + p) * SIZE + q; } vector<block> parents[COORD]; vector<coord> children[BLOCK]; void init() { for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { int p = i / UNIT * UNIT + j / UNIT; for (int k = 0; k < SIZE; k++) { coord c = coord_of(i, j, k); parents[c].push_back(block_of(GRD, i, j)); parents[c].push_back(block_of(ROW, i, k)); parents[c].push_back(block_of(COL, j, k)); parents[c].push_back(block_of(BOX, p, k)); } } } for (coord c = 0; c < COORD; c++) for (block b : parents[c]) children[b].push_back(c); } class no_solution_exception {} NO_SOLUTION_EXCEPTION; class sudoku { public: static string solve(string input) { try { sudoku s; return s.read(input).search().to_string(); } catch (no_solution_exception) { return "NO SOLUTION"; } } private: bool admit[COORD]; int count[BLOCK]; sudoku() { for (coord c = 0; c < COORD; c++) admit[c] = true; for (block b = 0; b < BLOCK; b++) count[b] = SIZE; } sudoku(const sudoku& s) { for (coord c = 0; c < COORD; c++) admit[c] = s.admit[c]; for (block b = 0; b < BLOCK; b++) count[b] = s.count[b]; } sudoku& search() { int min = DEFINED; int bmin = -1; for (block b = 0; b < BLOCK; b++) { if (count[b] < min) { min = count[b]; bmin = b; } } if (min == DEFINED) return *this; for (coord c : children[bmin]) { if (admit[c]) { try { sudoku s(*this); return s.assign(c).search(); } catch (no_solution_exception) { } } } throw NO_SOLUTION_EXCEPTION; } sudoku& read(string input) { int l = min(int(input.length()), SIZE * SIZE); for (int ij = 0; ij < l; ij++) { int k = DIGITS.find(input[ij]); if (k != -1) assign(coord_of(ij / SIZE, ij % SIZE, k)); } return *this; } sudoku& assign(coord c) { queue<coord> queue; queue.push(c); while (! queue.empty()) { int c0 = queue.front(); queue.pop(); if (! admit[c0]) throw NO_SOLUTION_EXCEPTION; for (block b1 : parents[c0]) { count[b1] = DEFINED; for (coord c2 : children[b1]) if (c2 != c0 && admit[c2]) { admit[c2] = false; for (block b3 : parents[c2]) if (b3 != b1) { count[b3]--; if (count[b3] == 0) throw NO_SOLUTION_EXCEPTION; if (count[b3] == 1) for (coord c4 : children[b3]) if (admit[c4]) queue.push(c4); } } } } return *this; } string to_string() { string output; for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { vector<int> ks; for (int k = 0; k < SIZE; k++) if (admit[coord_of(i, j, k)]) ks.push_back(k); if (ks.size() == 1) output += DIGITS[ks[0]]; else output += '.'; } } return output; } }; int main() { init(); string input; while (cin >> input) cout << sudoku::solve(input) << endl; return 0; }
原始碼中用到了部分c++ 2011標準的功能,但vc 2015沒有實現,比如and和not關鍵字。把它們改為 &&和!後,編譯通過,在連結時,預設需要和windows sdk中的uuid.lib連結,改用/MD選項,與kernel32.lib連結通過。
D:\>cl sudoku.cpp /EHsc /MD /O2 /link D:\VS2010SP1\WINSDK_v7.0A\Lib\kernel32.lib 用於 x86 的 Microsoft (R) C/C++ 優化編譯器 19.00.23026 版 版權所有(C) Microsoft Corporation。保留所有權利。 sudoku.cpp Microsoft (R) Incremental Linker Version 14.00.23026.0 Copyright (C) Microsoft Corporation. All rights reserved. /out:sudoku.exe D:\VS2010SP1\WINSDK_v7.0A\Lib\kernel32.lib sudoku.obj D:\>a\timer sudoku <sudoku17.16000.txt >sudoku17.16000_vc15.txt Timer 3.01 Copyright (c) 2002-2003 Igor Pavlov 2003-07-10 Kernel Time = 0.156 = 00:00:00.156 = 9% User Time = 0.998 = 00:00:00.998 = 60% Process Time = 1.154 = 00:00:01.154 = 70% Global Time = 1.638 = 00:00:01.638 = 100%
最終時間是1.6秒,同樣的機器上,pypy執行python版本是3.76秒,csc編譯cs後執行是3.9秒。命令列引數分別是
\timer pypy d:\sudoku.py d:\sudoku17.16000.txt >d:\sudoku17_16000py.txt \timer sudoku <d:\sudoku17.16000.txt >d:\sudoku17_16000cs.txt
說明:他的cs版本也用到了新功能,除了安裝.net framwork 4.62外,還要更新c#編譯器。 nuget工具是從csc提示的連線處下載的。
D:\>c:csc sudoku.cs Microsoft (R) Visual C# Compiler version 4.6.1590.0 for C# 5 Copyright (C) Microsoft Corporation. All rights reserved. This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to C# 5, which is no longer the latest version. For compilers that support newer versions of the C# programming language, see http://go.microsoft.com/fwlink/?LinkID=533240 D:\>nuget install Microsoft.Net.Compilers D:\>Microsoft.Net.Compilers.1.3.2\tools\csc sudoku.cs Microsoft (R) Visual C# Compiler version 1.3.1.60621 Copyright (C) Microsoft Corporation. All rights reserved.
相關文章
- 求解數獨
- 僅50行Python程式碼!數獨求解!4秒!Python
- 求解c++C++
- 求區間不同數的個數【主席樹求解】
- 另一個Swoole偵錯程式 - Yasd
- c++求解獎券題目C++
- python中怎麼呼叫另一個程式Python
- c++求解李白喝酒問題C++
- 求區間不同數的個數【樹狀陣列求解】陣列
- 列表切片賦值給另一個變數賦值變數
- 斯特林數求解
- 第一個C++程式C++
- 華納雲:linux怎麼將一個變數賦給另一個變數Linux變數
- 程式設計題求解程式設計
- 另一個go命令列引數處理器 - cmdrGo命令列
- [演算法] 兩個質數的乘積是707829217,求解該質數演算法
- 大數翻倍法求解CRT
- 變數C++邏輯程式碼變數C++
- 解讀第一個C++程式C++
- 一個隨機數的類c++隨機C++
- 表示式求解(非一位數)
- 梯度下降法中導數的求解梯度
- 1102:與指定數字相同的數的個數(C C++)C++
- uniapp js 數獨小遊戲 寫死的簡單數獨 數獨 3.0APPJS遊戲
- MongoDB關聯另一個集合MongoDB
- 求解一個陣列的所有子集陣列
- C++程式設計基礎(2)變數C++程式設計變數
- C++的函數語言程式設計C++函數程式設計
- C++取反交換兩個數的值C++
- C++ - 比較兩個浮點數大小C++
- 列表切片賦值給另一個變數,淺拷貝原理解析賦值變數
- 用c++設計哲學家進餐問題的求解C++
- 回溯演算法求解橋本分數式演算法
- Cplex混合整數規劃求解(Python API)PythonAPI
- 伯努利數,求解自然數冪和的關鍵係數
- 另一個Android效能剖析工具——simpleperfAndroid
- 樹的另一個構建方式
- C++程式語言的四個準則C++
- 從一片森林(JavaScript)到另一片森林(C++)JavaScriptC++