1. 程式人生 > >【Codeforces 111C】Petya and Spiders

【Codeforces 111C】Petya and Spiders

集合 class 方向 過程 可能 是否 新的 沒有 math

Codeforces 111 C

題意:給\(n\times m\)的網格,每個點上有一個蜘蛛,每個蜘蛛可以向上、下、左、右走一步或者不動,問最多能存在多少沒有蜘蛛的點。

思路1:

首先因為\(n\)\(m\)中小的那個不可能超過\(6\),所以欽定\(m < n\)(因為如果\(n\)\(m\)互換不影響答案)。

然後就可以考慮狀壓\(dp\)了。

首先我們看\((x,y)\)這個點上面可愛的小蜘蛛的去向。它可能會往上走,到\((x-1,y)\);也可能向下走,到\((x+1,y)\);也可能向左右走;所以就會發現在不斷向下一個點移動的過程中,對於\((x,y)\)有影響的是從\((x-1,y)\)

\((x+1,y)\)\(2\times m+1\)個點。所以\(dp\)狀態和轉移方程都可以求出辣:\(dp(x,y,mask)\)表示到了\((x,y)\)這個點,\(mask\)表示從\((x-1,y)\)\((x+1,y)\)的點是否是蜘蛛集合點。

轉移方程和\((x,y)?\)上的蜘蛛往哪個方向去走有關,或者它停在原地,它去的那個點必須是蜘蛛集合點,如果原來不是,那麽答案必須加1。然後轉移到下一個點即可。

思路2:

首先還是欽定\(m < n\)

然後還是考慮狀壓\(dp\),其狀態為\(dp(x,mask)\)。表示第\(x\)行時的狀態。

這裏\(mask\)保存的是當前行和上一行的所有的蜘蛛是否已經有地方去,然後轉移的時候用\(dfs\)

枚舉一行中哪些點作為集合點(這裏需要枚舉所有集合點的集合),同時將其四周的點的狀態賦為有地方去,然後讓當前行的上一行不要有沒地方去的點,繼續考慮下一行的\(dp\)

思路3:

欽定\(m < n?\),考慮狀壓\(dp?\),其狀態為\(dp(x,mask)?\)

這裏\(mask\)保存的是當前行與上一行的集合點集,\(dp\)的值是考慮最多的空閑點的個數。

轉移的時候枚舉這一行新的集合點集以及下一行的集合點集,然後判斷是否有當前行原來是集合點而現在不是的,有沒有當前行沒地方去的點,如果都沒有就可以進入下一行的\(dp\)

總結:

這3種思路較快的是思路1、2,然後較慢的是思路3,因為思路1的時間復雜度是\(O(n\times m\times 2^{2\times m+1})\)

,思路2的復雜度是\(O(n\times2^{3\times m})\),思路3的復雜度是\(O(n\times2^{4\times m})\)

由此可見,狀壓\(dp\)的狀態選擇方面,對於復雜度是有非常大的影響的。

【Codeforces 111C】Petya and Spiders