[算法模板]SOS DP
正文
SOS-DP(\(\text{Sum over Subsets}\))是用來解決這樣的問題的:
其實就是子集和DP。上面每個\(F[mask]\)里面包含了\(mask\)所有二進制子集的信息。這是一種\(n\log_2 n\)的DP方法。
我們定義一個DP狀態\(S(mask,i)\)代表\(mask\)子集中只有最靠右的\(i\)位與其不同的狀態。
具體是這樣的:
圖中描述了\(S(10110,4)\)這個狀態和其所有兒子之間的關系。
形象一些解釋就是每次我們求解一個狀態時,我們只從他的所有子集里和他只差一位的狀態轉移過來。(眾所周知,如果\(A\subseteq B,B\subseteq C\)那么\(A\subseteq\) C)。
放一段代碼:
for(int i = 0; i<(1<<N); ++i)
F[i] = A[i];
for(int i = 0;i < N; ++i) for(int mask = 0; mask < (1<<N); ++mask){
if(mask & (1<<i))
F[mask] += F[mask^(1<<i)];
}
所以顯然,復雜度\(N\space 2^N\)。如果令值域為\(M\),那么復雜度就是\(M\log_2M\)。
例題
參考資料
SOS Dynamic Programming [Tutorial]