數獨的dlx構造:9*9個點每個點有9種選擇,這構成了dlx的729行,每行、列、陣有限制,均為9行(/列/陣),然後每行(/列/陣)都有九種數的情況,於是就有了3*9*9列,但是因為乙個位置只能選乙個,所以又有9*9列,每列連線乙個點的九種選數情況。
最終有4*9*9=324列,9*9*9=729行。
具體看處理:
有些點已經有數了,但是這並不重要,我們只需要給這個點加上乙個行,為它已經選的數,而不要把9種情況都加上,這樣在有精確覆蓋的情況下(即有解),第四部分的某列在縱向就只連線乙個節點,顯然這個節點是必選的,所以不會出錯(當然你要是依然給這個有值節點在dlx中加9行的話,那我也沒招,不要問我為什麼錯,好吧你不會這麼傻吧?)。
而其它沒有初始值的數獨點,自然就加舊行了沒疑問吧?
說乙個跟空間複雜度相關的事,就是一行有且僅有4個節點,分別在行、列、陣、位置這四部分的列中,那麼總節點數(不算輔助節點)就應該最多是729*4,而實際上標準數獨都是有唯一解的,所以需要的節點將遠遠小於這個數。
再說說時間複雜度:因為我們可以為dlx加乙個優化,就是每次選乙個列中節點最少的列繼續dlx的過程,所以我們雖然保留了已經有值的節點,但是實際上最開始就選擇了它們,而若數獨有解,這也是必定選擇的,所以並不會出現因為層數過多而導致回溯過度而tle的情況,也就是說它還是很快的。
#include#include#includeusing namespace std;
const int inf=0x3f3f3f3f;const int maxn=3645;//每乙個格仔可能有9個取值。
//所以最多有81*9行。然後243列。
int u[maxn],d[maxn],l[maxn],r[maxn],c[maxn],row[maxn];//上下左右指標。
//c[i]結點i相應的列。row[i]結點i相應的行號。
int s[350],h[800],ans[100];//s[i]為i列1的個數。
//h[i]為i行的尾指標。
int n,m,cnt,deep;
struct node
st[maxn];
char maze[150],path[150];
void init()
r[324]=deep=0;
cnt=325;
}void insert(int r,int c)
s[c]++;//更新附加資訊
row[cnt]=r;
c[cnt++]=c;
}void remove(int c)//移除c列。
void resume(int c)//還原c列。
bool dfs()
resume(c);
return false;
}int main()
}else}}
dfs();
for(i=0;ipath[deep]=0;
printf("%s\n",path);
}return 0;
}
C 解決數獨問題(回溯)
參考鏈結來自於 輸入乙個數獨作為9 9的陣列,例如輸入乙個測試資料map 9 9 為 0 9 0 0 0 0 0 6 0 8 0 1 0 0 0 5 0 9 0 5 0 3 0 4 0 7 0 0 0 8 0 7 0 9 0 0 0 0 0 9 0 8 0 0 0 0 0 6 0 2 0 7 0 0...
數獨c 解決 dfs 減枝
刷華為的機試題 傳送門 數獨 刷到了乙個關於數獨的題目,以為數獨還有什麼特殊的解,自己寫了個減枝的dfs過了83 的資料,但是好多同學都有同樣的問題,估計使題目的問題把,這題有多解但是做法不同,就有不同的答案,但是答案都是正確的,然後test有只有乙個這就很惱火,所以就假裝我這是正確的吧。以前聽說過...
舞蹈鏈 精確覆蓋,解決數獨問題
首先看看數獨問題 9 9的方格 的規則 1 每個格仔只能填乙個數字 2 每行每個數字只能填一遍 3 每列每個數字只能填一遍 4 每宮每個數字只能填一遍 那現在就是利用這個規則把數獨問題轉換為精確覆蓋問題 可是,直觀上面的規則,發現比較難以轉換為精確覆蓋問題。因此,把上面的表述換個說法 1 每個格仔只...