題目地址 https://www.acwing.com/problem/content/description/168/ios
題目描述數組
數獨是一種傳統益智遊戲,你須要把一個9 × 9的數獨補充完整,使得圖中每行、每列、每一個3 × 3的九宮格內數字1~9均剛好出現一次。ide
請編寫一個程序填寫數獨。函數
輸入格式
輸入包含多組測試用例。測試
每一個測試用例佔一行,包含81個字符,表明數獨的81個格內數據(順序整體由上到下,同行由左到右)。優化
每一個字符都是一個數字(1-9)或一個」.」(表示還沒有填充)。spa
您能夠假設輸入中的每一個謎題都只有一個解決方案。code
文件結尾處爲包含單詞「end」的單行,表示輸入結束。blog
輸出格式
每一個測試用例,輸出一行數據,表明填充徹底後的數獨。遊戲
樣例
輸入樣例: .2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534. ......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3. end 輸出樣例: 527389416819426735436751829375692184194538267268174593643217958951843672782965341 416837529982465371735129468571298643293746185864351297647913852359682714128574936
法1
時間卡的比較緊,搜索上作了許多優化
1 進行可填寫數據的篩選.因爲數獨自己的性質,1~9同一數字不能在同一行 同一列 同一九宮格出現兩次以上。
我開始計劃是開一個 9*9的數組記錄每一個格子可能出現的數字.每次確認填寫一個數字 就更新同行同列同九宮格里的記錄
可是這樣的話,每次填寫一個數字及須要更新 一行9個 一列9個 和九宮格九格的數據。共27個數據。
YXC大佬的代碼 使用的 行記錄一個 列記錄一個 九宮格記錄一個 這樣只須要更新三個數據便可
2 優化填寫格子的策略,每一個格子可填寫的數據比較少的優先選取。 這也是剪枝的一種.
代碼見
//找到可選方案數最少的空格 int minv = 10; int x, y; for(int i = 0;i < N;i++) for(int j = 0;j < N;j++) if (str[i*9+j] == '.') { int t = ones[get(i, j)]; if (t < minv) { minv = t; x = i, y = j; } }
3 一些其餘小技巧,使用位來記錄該空格可填寫那些數字
000000001 表示可填寫1
000000010 表示可填寫2
000000100 表示可填寫3
000000101 表示可填寫1和3
......
x = 000000111 表示可填寫1 2 3。 若是咱們當前選擇填寫2 那麼只要 x - (1<<(2-1))就能夠把填寫2的表示去除了
代碼裏不是2-1 而是 可填寫的數字的字母的實際值與 ‘1’的差值
4 判斷是不是統一九宮格 採用 x/3==i/3 y/3 == j/3
還有其餘一些小技巧 歡迎一塊兒討論
1 #include <iostream> 2 #include <algorithm> 3 #include <set> 4 5 using namespace std; 6 7 const int N = 9; 8 9 int row[N], col[N],cell[3][3]; 10 11 char str[100]; 12 13 int ones[1 << N],map[1<<N]; 14 15 inline int lowbit(int x) { 16 return x & -x; 17 } 18 19 void init() 20 { 21 for (int i = 0; i < N; i++) row[i] = col[i] = (1 << N) - 1; 22 for (int i = 0; i < 3; i++) 23 for (int j = 0; j < 3; j++) 24 cell[i][j] = (1 << N) - 1; 25 } 26 27 inline int get(int x, int y) 28 { 29 return row[x] & col[y] & cell[x / 3][y / 3]; 30 31 } 32 33 bool dfs(int cnt) 34 { 35 if (!cnt) return true; 36 37 //找到可選方案數最少的空格 38 int minv = 10; 39 int x, y; 40 for(int i = 0;i < N;i++) 41 for(int j = 0;j < N;j++) 42 if (str[i*9+j] == '.') { 43 int t = ones[get(i, j)]; 44 if (t < minv) { 45 minv = t; 46 x = i, y = j; 47 } 48 } 49 50 for (int i = get(x, y); i; i -= lowbit(i)) { 51 int t = map[lowbit(i)]; 52 53 //修改狀態 54 row[x] -= 1 << t; 55 col[y] -= 1 << t; 56 cell[x / 3][y / 3] -= 1 << t; 57 str[x * 9 + y] = '1' + t; 58 if (dfs(cnt - 1)) return true; 59 60 //回覆現場 61 row[x] += 1 << t; 62 col[y] += 1 << t; 63 cell[x / 3][y / 3] += 1 << t; 64 str[x * 9 + y] = '.'; 65 } 66 67 68 return false; 69 } 70 71 int main() 72 { 73 for (int i = 0; i < N; i++) map[1 << i] = i; 74 for (int i = 0; i < 1 << N; i++) { 75 int s = 0; 76 for(int j = i; j;j -= lowbit(j)) s++; 77 ones[i] = s; //i的二進制表示中有s個1 78 } 79 80 while (cin >> str, str[0] != 'e') { 81 init(); 82 int cnt = 0; 83 for(int i =0,k = 0;i < N;i++) 84 for(int j = 0; j < N;j++,k++) 85 if (str[k] != '.') { 86 int t = str[k] - '1'; 87 row[i] -= 1 << t; 88 col[j] -= 1 << t; 89 cell[i / 3][j / 3] -= 1 << t; 90 } 91 else { 92 cnt++; 93 } 94 95 dfs(cnt); 96 cout << str << endl; 97 } 98 99 return 0; 100 101 } 102 103 做者:defddr 104 連接:https://www.acwing.com/solution/AcWing/content/2294/ 105 來源:AcWing 106 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
1 // 11111111.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。 2 // 3 4 #include <iostream> 5 #include <map> 6 #include <vector> 7 #include <string> 8 #include <stdio.h> 9 10 using namespace std; 11 12 13 14 /* 15 .2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534. 16 ......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3. 17 end 18 */ 19 20 21 const int N = 9; 22 23 int map1[1 << N]; 24 int Xarr[N]; 25 int Yarr[N]; 26 int SameXYArr[N / 3][N / 3]; 27 28 int ones[1 << N], map[1 << N]; 29 30 char str[100]; 31 32 void Init() 33 { 34 for (int i = 0; i < N; i++) { 35 Xarr[i] = (1 << N) - 1; 36 Yarr[i] = (1 << N) - 1; 37 map1[1 << i] = i; 38 } 39 40 for (int i = 0; i < N / 3; i++) { 41 for (int j = 0; j < N / 3; j++) { 42 SameXYArr[i][j] = (1 << N) - 1; 43 } 44 } 45 } 46 47 inline int lowbit(int x) { 48 return x & -x; 49 } 50 51 inline int get(int x, int y) 52 { 53 return Xarr[x] & Yarr[y] & SameXYArr[x / 3][y / 3]; 54 } 55 56 bool Dfs(int count, char str[]) 57 { 58 if (!count) return true; 59 60 int minv = 10; 61 int minx = -1; int miny = -1; 62 63 for (int x = 0; x < 9; x++) { 64 for (int y = 0; y < 9; y++) 65 { 66 if (str[x * 9 + y] == '.') { 67 int t = ones[get(x,y)]; 68 69 if (t < minv) { 70 minv = t; 71 minx = x; 72 miny = y; 73 } 74 } 75 } 76 } 77 78 if (0 == minv) 79 return false; 80 81 int tryNums = get(minx, miny); 82 83 84 while (tryNums != 0) { 85 int trynum = map1[lowbit(tryNums)]; 86 87 Xarr[minx] -= 1 << trynum; 88 Yarr[miny] -= 1 << trynum; 89 SameXYArr[minx / 3][miny / 3] -= 1 << trynum; 90 str[minx * 9 + miny] = '1' + trynum; 91 92 if (Dfs(count - 1, str)) return true; 93 94 //回覆現場 95 Xarr[minx] += 1 << trynum; 96 Yarr[miny] += 1 << trynum; 97 SameXYArr[minx / 3][miny / 3] += 1 << trynum; 98 str[minx * 9 + miny] = '.'; 99 100 tryNums -= lowbit(tryNums); 101 } 102 103 return false; 104 } 105 106 void Do(char str[]) 107 { 108 Init(); 109 int count = 0; 110 for (int i = 0; i < 9; i++) { 111 for (int j = 0; j < 9; j++) { 112 if (str[i * 9 + j] != '.') { 113 int idx = 1 << (str[i * 9 + j] - '1'); 114 Xarr[i] -= idx; 115 Yarr[j] -= idx; 116 SameXYArr[i / 3][j / 3] -= idx; 117 } 118 else { 119 count++; 120 } 121 } 122 } 123 124 Dfs(count, str); 125 cout << str << endl; 126 127 return; 128 } 129 130 131 int main() 132 { 133 ios::sync_with_stdio(false); 134 135 for (int i = 0; i < N; i++) map1[1 << i] = i; 136 for (int i = 0; i < 1 << N; i++) { 137 int s = 0; 138 for (int j = i; j; j -= lowbit(j)) s++; 139 ones[i] = s; //i的二進制表示中有s個1 140 141 } 142 143 while (cin >> str, str[0] != 'e') { 144 //s = ".2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534."; 145 146 Do(str); 147 } 148 149 150 }