AcWing 166. 數獨

題目地址 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 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
View Code

 

  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 }
View Code
相關文章
相關標籤/搜索