1. 程式人生 > 其它 >塗色——區間dp

塗色——區間dp

P4170 [CQOI2007]塗色 - 洛谷 | 電腦科學教育新生態 (luogu.com.cn)

一道很好的題。一定要明確dp問題就是分析狀態的,不要太細節,不要管每個區間內具體有什麼顏色。這道題看了大佬的題解後,真的有了很大的感觸。

大佬做法:

1.先判斷出來這是區間dp,然後畫數軸。

2.因為區間dp的核心思想是由一個個小區間進行合併成為了大區間,所以我們應該先模擬長度最小的區間,也就是長度為1的區間。

3.在研究長度為n的區間的時候,可以在數軸上標明覆蓋區間,更直觀。

4.以這道題為例

  1.長度為1的區間的值即塗色次數就是1

  2.長度為2的區間的值,是由兩個長度為1的區間進行合併

    1.如果兩個區間的顏色相同,塗色次數=其中一個長度為1的區間

    2.如果兩個區間顏色不相同,塗色次數=兩個長度為1的區間塗色次數之和

  3.長度為3的區間的值,由一個長度為2的區間+一個長度為1的區間合併

    1.這時候就要思考狀態轉移方程式了

    2.利用數軸,標明各種情況,思考不同情況下需要寫出來的狀態轉移方程式

    3.設此時研究的區間左右端點為i與i+2 (一般化)

    

  觀察整個區間,拿支熒光筆畫一下,長度為3的區間,

  • 這道題目給人以區間dp的一種新的理解,不能過於拘泥在 列舉區間內中的分割點,還可以直接使用區間內某個特定的分割點,什麼意思呢? - 只要左端點的顏色 == 右端點的顏色,合併左右區間的時候

  • 可以直接轉移左區間或者右區間,因為我們可以直接一刷子塗滿整個區間

  • 不需要任何花費就能向外拓展一個格子。

  • 此時我們發現,我們可以把左右區間的顏色相等情況單獨的分離出來,

  • 即f [ i , j ] = min ( f [ i + 1 ] [ j ] , f [ i ]  [ j -1 ] )

  • 當左右區間的顏色不符合的時候,用你最拿手的狀態轉移方程式
  • 即f [ i , j ] = min ( f [ i ,  j ] , f [ i , k ] + f [ k + 1 , j ] )
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=60;
 4 char
a[N]; 5 int f[N][N]; 6 7 int main() 8 { 9 10 scanf("%s",a+1); 11 int n=strlen(a+1); 12 memset(f,0x3f,sizeof f); 13 for(int len=1;len<=n;len++) 14 { 15 for(int i=1;i+len-1<=n;i++) 16 { 17 int j=len+i-1; 18 if(i==j) 19 { 20 f[i][j]=1; 21 continue; 22 } 23 if(a[i]==a[j])f[i][j]=min(f[i+1][j],f[i][j-1]); 24 else 25 { 26 for(int k=i;k<j;k++) 27 f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]); 28 } 29 } 30 } 31 32 printf("%d\n",f[1][n]); 33 34 return 0; 35 }
View Code