【容斥原理+狀態壓縮】zjoi2009 多米諾骨牌
徹徹底底的被這道題虐了,想了一個月沒想出來,最後和宇宙大總統一起強肯了2個小時標程算是看懂了。。
首先拋開這道題的那個奇怪的限制(沒行列沒有骨牌跨過),一個赤裸裸的骨牌覆蓋我都不不知道怎麼做啊!!
先看下赤裸裸的骨牌覆蓋怎麼做:
一般人的反映就會想到狀態壓縮DP,沒錯
狀態為F【I,J】表示第i行的狀態為J的方案數>>空間複雜度O(N*2^N),轉移O(2^N),寫的好的話可以做到時間複雜度為O(N*3^N),TLE!
實際上有著麼一種更加好寫方法,類似CDQ論文中所說的輪廓線,這樣設計狀態>>F【I,J,K】表示從(i,1)到(i,j-1)、從(i-1,j)到(i-1,m)的狀態為K的方案數。這樣轉移的複雜度為O(1),看上去就可以解決這道題了。
我們利用如上所述的方法DP出A【I,J,K,L】表示子矩形(I,J,K,L)的一頓亂放的方案數。
現在在繼續考慮怎麼完成那個奇怪的限制,我們需要請出容斥原理大俠。。
由於橫豎都有限制,而容斥原理又不好擴充套件到2維,所以我們需要在一維上進行容斥原理,在另外一維進行DP,這個DP也比較巧妙,需要用到補集轉化的思想,感覺和POJ男人八題的那個啥挺像的(不記得了,應該是求一個點有區別的無向圖的聯通圖個數)。
據說H8OJ解除了pas的“四相封印”,不過我交上去還是墊底了。。。
從QZC神哪裡學來的幾個很搞笑的東西:
定義一個數組指標,比如
a:^array[0..100] of longint;
b:array[0..100] of longint;
用這麼一個玩意:a:[email protected];
然後a^實際上就是b這個陣列了,在做高維DP的時候如果你寫個F【I,J,K,L,。。。。。。】估計程式會很恐怖,可以用這個來優化下程式碼量,而且速度估計也會快一點。