1. 程式人生 > >hihocoder-1048 狀態壓縮·二(狀壓DP)

hihocoder-1048 狀態壓縮·二(狀壓DP)

小Ho的觀察力一向不錯,這不,他很快便發現了M的取值範圍只可能為3、4、5三種情況,但是這一發現並沒有能夠給他減輕多少煩惱。

雖然在過去一段時間的訓練下,小Ho很快就意識到這道題目可能仍然是需要使用動態規劃進行解決,但是他苦思冥想也沒有能夠想到很好的狀態定義方式:“如果我每次列舉一塊蛋糕的放置位置,那麼我就需要儲存下整個盤子的放置情況——也就是說2的(N*M)次方種狀態,存不下呀存不下!”

小Hi看著小Ho憋悶的樣子,也是知道他想錯了方向,於是道:“你先別急,讓我們從頭來看看這個問題,首先你先告訴我,我們的問題是甚麼?”

小Ho搖了搖頭,想了想,道:“有多少種方案可以用1*2的正方形填滿一個N*M的長方形?”

小Hi笑道:“是的,我們不妨稱這個答案為sum(N, M),那麼我們接下來要做的事情是不是要想辦法把這個問題分解成若干子問題呢?”

小Ho道:“是的,我之前也是想到這裡,我首先列舉一塊蛋糕的放置位置,那麼剩下的空閒位置有多少種方案被填滿就是一個子問題了!由於這個位置的數量是在一直減少的,所以我可以按照一定的順序依次求解出所有這樣的問題的答案,但是這樣的問題的數量太多了,根本計算不過來。”

小Hi道:“你可是想的太簡單了呢,真的只有算不過來的問題麼?你且看這兩種情況,雖然我第一次列舉的位置不同,但是隻要第二次列舉的是另一種情況的第一次列舉,那麼最終都會到達同樣的狀態,那麼接下來是不是就會出現重複的統計啊?”

小Ho驚道:“是這樣!那……那我應該怎麼辦呢?”

小Hi笑道:“我有一計,可解上述兩大難題!”

小Ho道:“快快道來!”

小Hi揮揮手,表示不要著急,接著說:“你看!對於這樣一種方案,按照你之前的方法,無論是1234的順序列舉,還是4321的順序列舉,最後統計到的都是這樣一種方案,也就是無論是1~4的哪一種排列,都會是這樣的方案,那麼是不是說明,每一種方案都被統計了(N*M)!次?

小Ho點了點頭道:“是的!”想了想又接著說:“那麼我是不是隻要把最終答案都除以(N*M)!就能夠得到正確的答案了呢?”

小Hi滿臉無奈道:“真是個沒志氣的傢伙,你為什麼不乾脆想辦法使得每種方案都只被統計一次呢?”

小Ho:“怎麼做?!教教我~”

小Hi道:”你想想,既然無論以什麼樣的排列順序都會致使同樣的結果,那麼我們就想辦法給它定義一個順序便是了呢?比如說,對於每一塊蛋糕,以其左(上)邊一塊的行號為第一關鍵字,列號為第二關鍵字的順序,只有按照這個順序遞增的排列才是合法的!

小Ho低頭算了算,道:”是的!這樣就只有1234這樣一種順序合法了,同樣的,其他的每一種方案也都會只有一種對應的方案。但是我仍然不懂的是,我怎麼保證在求解這個子問題的時候,一定能夠只搜尋出這樣的方案呢?“

小Hi道:”這個簡單!只要不是列舉每一塊蛋糕放在什麼地方?而是按照行號為第一關鍵字,列號為第二關鍵字的順序,依次列舉每個位置上的蛋糕是如何放置的!通過這樣的方式,來將一個問題分解成子問題!比如在下面的這個問題中,我當前要決定的便是黑色方塊的蛋糕放置方案,而不同的放置方案——橫放還是豎放,便會匯出不同的子問題,並且這樣是不會像之前的方法那樣,有重複統計的。”

小Ho道:“原來是這樣!仔細想想就會發現,這樣匯出的方案一定是符合我們之前的要求的,是合法的!但是不是說要解決兩個問題麼,現在我似乎還是要記錄棋盤的局面呀,不然的話出現這種情況的時候,我是沒有辦法知道當前這個位置是否可以橫放豎放,又是否已經在之前的放置中已經放置過了!”

小Hi忙道:“別急別急,你再想想到底要記錄多少東西~”

“唔……其實好像只用記錄兩行就可以了!因為在列舉到(i, j)這個位置的時候,也就是當前列舉的位置所在的這一行,以及下一行。因為這之前的位置肯定都已經放置滿了蛋糕,而這之後的位置肯定都還沒有放置任何東西!”小Ho恍然大悟道。

“那你準備如何定義狀態呢~”

“像這樣,我令sum(i, j, p1, p2, ... , pM, q1, q2, ... , qM)表示:已經將第一行至第i-1行的盤子都已經填滿了,當前正在嘗試往(i, j)這個位置放置蛋糕,而第i行的放置情況用p1...pM表示,第i+1行的放置情況用q1...qM表示——0表示為空,1表示放置了蛋糕。那麼sum(i, j, p1, p2, ... , pM, q1, q2, ... , qM)便表示在這種情況下,剩餘的格子有多少種填充的方法,而我們要求的問題便是sum(1, 1, 0, 0, 0, ..., 0)了!”

小Hi笑道:“誒,你居然注意到了這個問題要求的是sum而不是best~這並不像之前的動態規劃一樣是求一個全域性最優解,而是單純的統計方案數!”

小Ho拍拍胸脯道:“你也不看看我是誰!而我覺得轉移會是這樣的……其中第一、二種情況是用於當前位置並不是空白位置時;第三種到第六種分別代表著當前位置的蛋糕擺放方向的2*2種可能。

檢視大圖

小Hi點了點頭,道:“沒錯!那你有沒有覺得你這樣的狀態定義還是沒有辦法很好的根據M來進行轉移?”

小Ho驚道:“是的呢!對了!我們還可以用上一週說的那種“狀態壓縮”的方式,將p1 ... pM, q1 ... qM 這2M個0/1表示成為一個整數,這樣我的狀態轉移方程就會變成這樣了!其中si表示s轉換為2進位制後從高到低第i位的值~”

檢視大圖

“是的呢!”小Hi點了點頭:“趕緊去寫個程式算出來,我們就可以去吃蛋糕了!”