dfs硬懟經過數獨 N皇后的代碼後 想學習下新的數據結構和算法來解決這類覆蓋問題html
習題練習node
https://www.acwing.com/problem/content/168/ 數獨ios
https://www.acwing.com/problem/content/171/ 數獨2算法
https://www.acwing.com/problem/content/185/ 靶形數獨數組
資料收集以下 進行學習數據結構
http://www.javashuo.com/article/p-kqgjimbg-g.html數據結構和算法
http://www.javashuo.com/article/p-xvtetkog-u.htmlide
https://blog.csdn.net/whereisherofrom/article/details/79220897函數
習題學習學習
洛谷
https://www.luogu.org/problem/P4929 P4929 【模板】舞蹈鏈(DLX)
https://www.luogu.org/problem/P1074 P1074 靶形數獨
https://www.luogu.org/problem/P1219 P1219 八皇后
題解
https://www.luogu.org/blog/ONE-PIECE/qian-tan-dlx 【模板】舞蹈鏈(DLX)
https://www.luogu.org/blog/ONE-PIECE/ba-xing-shuo-du-dai-ma 靶形數獨
https://www.luogu.org/blog/ONE-PIECE/solution-p1219 八皇后
個人對模板註釋的代碼 參考的源代碼地址https://www.luogu.org/blog/ONE-PIECE/qian-tan-dlx
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 5 6 //精確覆蓋問題的定義:給定一個由0-1組成的矩陣,是否能找到一個行的集合,使得集合中每一列都剛好包含一個1 7 const int MN = 9 * 9 * 9 + 10;//最大行數,共有9*9個格子,每一個格子能夠放1~9 8 const int MM = 9 * 9 + 9 * 9 + 9 * 9 + 9 * 9 + 100;//最大列數 9 const int MAX_NUM = MN * MM; //最大點數 10 11 struct DLX 12 { 13 int n, m, idx;//n行數m列數idx 元素索引 14 //十字鏈表組成部分 15 16 int l[MAX_NUM], r[MAX_NUM], u[MAX_NUM], d[MAX_NUM]; //記錄某個idx索引點的上下左右點的索引 17 int col[MAX_NUM], row[MAX_NUM]; //二者結合使用 記錄某個idx索引點的行 列號 18 19 20 int nodeIdxPerRow[MAX_NUM]; //記錄每行的開頭節點的索引 21 int nodeNumPerCol[MAX_NUM]; //記錄每列節點的個數 22 23 24 int ansd, ans[MN]; 25 26 void init(int n ,int m) //初始化十字鏈表的 頭節點和 列節點表頭串 m表示有多少列 27 { 28 //初始化頭結點和 列節點表頭串 頭節點數組索引 = 0 列節點表頭共m個 索引 1~m 29 for (int i = 0; i <= m; i++) { 30 r[i] = i + 1; 31 l[i] = i - 1; 32 u[i] = d[i] = i; //列節點頭串只有互相橫向鏈接 上下鏈接均指向本身 33 } 34 r[m] = 0; 35 l[0] = m; //循環鏈接 col[m] 的右端指向頭節點 頭結點的左端指向clo[m] 36 37 memset(nodeIdxPerRow, 0, sizeof(nodeIdxPerRow)); 38 memset(nodeNumPerCol, 0, sizeof(nodeNumPerCol)); 39 40 idx = m + 1; //目前使用 0 頭結點 與 m個列節點表頭串 0~m 共m+1個節點 41 } 42 43 44 45 //插入節點 進行的一些數據記錄 46 void link(int insertRow, int insertCol) 47 { 48 nodeNumPerCol[insertCol]++; //插入一個節點 那麼該列的節點個數+1 49 row[idx] = insertRow; 50 col[idx] = insertCol; //記錄第idx個節點所在的行與列 51 52 u[idx] = insertCol; //當前插入的節點索引記錄 向上指向列節點頭串中的insertCol 53 d[idx] = d[insertCol]; //當前插入節點索引記錄 向下指向原來列節點頭串的向下指向點 54 u[d[insertCol]] = idx; //原來列節點頭串指向的節點 向上由指向列節點頭串指向插入的節點(使用索引) 55 d[insertCol] = idx; //列節點頭串則向下指向新插入的節點(使用索引) 56 57 //更新每行的節點記錄 nodeIdxPerRow 58 if (nodeIdxPerRow[insertRow] == 0) { 59 //若是該節點是第一個插入的節點 60 nodeIdxPerRow[insertRow] = r[idx] = l[idx] = idx;//該行沒有點,直接加入 61 } 62 else { 63 //若是不是第一個插入的節點 同上面處理列次序同樣 在記錄和第一個節點間 插入本函數插入的節點 64 r[idx] = nodeIdxPerRow[insertRow]; //新節點的右端指向原來行記錄中的第一個節點 65 l[idx] = l[nodeIdxPerRow[insertRow]]; //新節點的左端指向原來行記錄第一個節點的左端 也就是行記錄nodeIdxPerRow 66 r[l[nodeIdxPerRow[insertRow]]] = idx; //原來行記錄第一個節點的左端(也就是行記錄nodeIdxPerRow)的右端 指向新插入的點(使用索引) 67 l[nodeIdxPerRow[insertRow]] = idx; //原來行記錄第一個節點的左端指向新插入的節點(使用索引) 68 69 } 70 idx++; 71 return; 72 } 73 74 void remove(int deleteCol) {//刪除涉及C列的集合 75 //將要刪除的列的左右兩端鏈接起來 也等於將本身摘除出來 76 r[l[deleteCol]] = r[deleteCol], l[r[deleteCol]] = l[deleteCol]; 77 for (int i = d[deleteCol]; i != deleteCol; i = d[i]) { 78 for (int j = r[i]; j != i; j = r[j]) { 79 u[d[j]] = u[j]; 80 d[u[j]] = d[j]; 81 nodeNumPerCol[col[j]]--; 82 } 83 } 84 } 85 void resume(int resCol) {//恢復涉及C列的集合 86 for (int i = u[resCol]; i != resCol; i = u[i]) { 87 for (int j = l[i]; j != i; j = l[j]) { 88 u[d[j]] = j; 89 d[u[j]] = j; 90 nodeNumPerCol[col[j]]++; 91 } 92 } 93 r[l[resCol]] = resCol; 94 l[r[resCol]] = resCol; 95 } 96 97 98 99 bool dance(int deep) //選取了d行 100 { 101 if (r[0] == 0)//所有覆蓋了 102 { 103 //全覆蓋了以後的操做 104 ansd = deep; 105 return 1; 106 } 107 108 109 int c = r[0];//表頭結點指向的第一個列 110 for (int i = r[0]; i != 0; i = r[i])//枚舉列頭指針 111 { 112 if (nodeNumPerCol[i] < nodeNumPerCol[c])c = i; 113 114 } 115 116 remove(c);//將該列刪去 117 for (int i = d[c]; i != c; i = d[i]) 118 {//枚舉該列的元素 119 ans[deep] = row[i];//記錄該列元素的行 120 for (int j = r[i]; j != i; j = r[j]) 121 remove(col[j]);//將該列的某個元素的行上的元素所在的列都刪去 122 if (dance(deep + 1)) 123 return 1; 124 for (int j = l[i]; j != i; j = l[j]) 125 resume(col[j]); 126 } 127 resume(c); 128 return 0; 129 } 130 }dlx; 131 //========================================================== 132 133 134 char s[90], path[90]; 135 struct node 136 { 137 int r, c, v; 138 }nds[MN]; 139 int main() 140 { 141 while (~scanf("%s", s)) 142 { 143 if (s[0] == 'e')break; 144 dlx.init(9 * 9 * 9, 9 * 9 * 4); 145 int r = 1; 146 for (int i = 1; i <= 9; i++) 147 { 148 for (int j = 1; j <= 9; j++) 149 { 150 if (s[(i - 1) * 9 + j - 1] == '.') 151 { 152 for (int z = 1; z <= 9; z++) 153 { 154 dlx.link(r, (i - 1) * 9 + j); 155 dlx.link(r, 81 + (i - 1) * 9 + z); 156 dlx.link(r, 162 + (j - 1) * 9 + z); 157 dlx.link(r, 243 + (((i - 1) / 3) * 3 + (j + 2) / 3 - 1) * 9 + z); 158 nds[r].r = i, nds[r].c = j, nds[r].v = z; 159 r++; 160 } 161 } 162 else 163 { 164 int z = s[(i - 1) * 9 + j - 1] - '0'; 165 dlx.link(r, (i - 1) * 9 + j); 166 dlx.link(r, 81 + (i - 1) * 9 + z); 167 dlx.link(r, 162 + (j - 1) * 9 + z); 168 dlx.link(r, 243 + (((i - 1) / 3) * 3 + (j + 2) / 3 - 1) * 9 + z); 169 nds[r].r = i, nds[r].c = j, nds[r].v = z; 170 r++; 171 } 172 } 173 } 174 dlx.ansd = -1; 175 dlx.dance(0); 176 int deep = dlx.ansd; 177 for (int i = 0; i < deep; i++) 178 { 179 int posr = dlx.ans[i]; 180 path[(nds[posr].r - 1) * 9 + nds[posr].c - 1] = '0' + nds[posr].v; 181 } 182 path[deep] = '\0'; 183 printf("%s\n", path); 184 } 185 return 0; 186 }