題目連結:POJ 1390.Blocks
題意:
有n個方塊排成一列,每個方塊有顏色即1到n的一個值,每次操作可以把一段相同顏色的方塊拿走,長度為k,則獲得的分數為 \(k\times k\),求可獲得的分數最大值。
其中每次要把一段全部拿走,不能只取其中一部分。
每個測試點T組資料,\(T\leq15\) , \(n\leq200\) 。
想了好一會。。
思路:
根據題意這顯然是\(O(n^3)\)的區間DP,可以發現僅設兩個維度l,r不足以轉移資訊,考慮在每次合併兩個區間時,我們需要知道區間各自最後的顏色和最後該顏色方塊的數量(以維護將兩端合一起拿的情況),而根據複雜度我們只能記錄一個量,而且在轉移的時候不能列舉前繼狀態的該量(否則就至少\(O(n^4)\)了),我們發現,此時條件不允許我們關注區間內部的狀態,因此只能觀察外部的情況。
考慮一個色段從外面被合起來拿走,根據DP不重不漏的原則,我們只看最右邊的色段的情況,它被合著拿走的前提是此色段和外邊同色的色段中間的方塊已被取走,我們只需要關注他們的總數為多少以計算分數,這樣子,設計狀態\(dp[l][r][k]\)為在區間\([l,r]\)上,同時在\(a[r]\)右側還有\(k\)個與\(a[r]\)同色的方塊等著和左邊合併,此種狀態下它被全部取走所能獲得的最大分數。
我們先將所有色段統計大小後縮成格子,對於\(a[r]\),它有兩種選擇:
- 和右邊的\(k\)個格子合併(題意要求必須全部合併),\(c[r]\)為此格原來色段的長度
\[dp[l][r][k]=dp[l][r-1][0]+(c[r]+k)*(c[r]+k)
\]
- 和自己區間內的同色格子a[i]合併(自己加入等待合併的色段中),中間跳過的區間就沒有等待隊伍了,k=0。
\[dp[l][r][k]=dp[l][i][c[r]+k]+dp[i+1][r-1][0]
\]
預處理\(nxt[i]\)為在\(a[i]\)往前第一個和其同色的格子下標,\(rem[i][j]\)為從\(a[j]\)的下一位往後,顏色為\(i\)的方塊數量。
上程式碼: