關於做狀態壓縮DP的一些經驗(暫時持續更新)
阿新 • • 發佈:2018-12-17
關於做狀態壓縮DP的一些經驗
狀壓DP總是讓我絕望~~(蒟蒻噩夢)~~ 所以我就想寫一篇部落格來總結一發。(每道例題在我的部落格中都可以找到完整題解)
NO.1
其實有時候並不需要把狀態中每個狀態給表示出來,只要不影響狀態之間的轉移即可。
比如:
題目描述
約翰家有N頭奶牛,第i頭奶牛的編號是Si,每頭奶牛的編號都是唯一的。這些奶牛最近 在鬧脾氣,為表達不滿的情緒,她們在擠奶的時候一定要排成混亂的隊伍。在一隻混亂的隊 伍中,相鄰奶牛的編號之差均超過K。比如當K = 1時,1, 3, 5, 2, 6, 4就是一支混亂的隊伍, 而1, 3, 6, 5, 2, 4不是,因為6和5只差1。請數一數,有多少種隊形是混亂的呢? (1<=n<=16)
解法:
這道題我當初就是死在試圖把每頭牛的位置表示出來 但經過一番摸♂索,我發現,其實不需要知道每頭牛的位置。 只需知道每頭牛是否已經被選和最後一牛的是第幾只 因為如果用刷表法DP,每次狀態狀態轉移只會轉移合法狀態,所以其實並不需要關注牛內部的排序方式。 dp[j][i]表示第j頭牛是最後一隻,選牛的方案用二進位制表示為i。 主要程式碼
for(int i=0;i<(1<<n);++i)//列舉狀態
for(int j=0;j<n;++j) if(i&(1<<j))//列舉當前最後一隻牛
for(int k=0;k<n;++k) if(!(i& (1<<k)) && abs(a[j]-a[k]) > K)
//列舉可以轉移到新的最後一隻牛的狀態
dp[k][i|(1<<k)]+=dp[j][i];
for(int i=0;i<n;++i)//統計答案
ans+=dp[i][(1<<n)-1];
}