區間dp [D - Flood Fill] 暑訓第四天
阿新 • • 發佈:2020-07-06
區間dp D - Flood Fill
題目大意:
如果[l,r] 這個連續的區間的數都相等,則說明這個是一個連通塊,給你n個數,每一個數都代表這個位置的顏色,首先你要選取第一個操作的位置,之後你可以對這個位置所在的連通塊進行改變顏色,可以改變成任意顏色。問最少多少次操作可以讓這n個數變成一個顏色。
題解:
首先要重視這個操作的位置只有一個,就是最開始選取的。
使得 \([l,r]\) 這個區間最後都是一樣的顏色,那麼只能從 \([l+1,r]\) \([l,l]\) 和 $[l,r-1] $ $ [r,r]$這兩個狀態轉移過來。
我們可以假設第一個選取的位置在 \([l+1,r]\)
如果是從 \([l+1,r]\) 這個狀態轉移過來,那麼最後這個顏色應該是和 \(l\) 這個位置的顏色是一樣的。
如果是從 \([l,r-1]\) 這個狀態轉移過來,那麼最後這個顏色應該是和 \(r\) 這個位置的顏色是一樣的。
所以需要第三維,對於區間 \([l,r]\) 0表示從 \(l\) 轉移過來,1表示從 \(r\) 轉移過來。
#include <bits/stdc++.h> #define id first #define val second #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn=5e3+10; int dp[maxn][maxn][2],a[maxn]; int main(){ int n; scanf("%d",&n); memset(dp,inf,sizeof(dp)); for(int i=1;i<=n;i++) scanf("%d",&a[i]),dp[i][i][0]=dp[i][i][1]=0; for(int len = 2;len<=n;len++){ for(int i=1;i+len-1<=n;i++){ int j=i+len-1; dp[i][j][0]=min(dp[i+1][j][1]+(a[j]!=a[i]),dp[i+1][j][0]+(a[i+1]!=a[i])); dp[i][j][1]=min(dp[i][j-1][0]+(a[j]!=a[i]),dp[i][j-1][1]+(a[j-1]!=a[j])); } } printf("%d\n",min(dp[1][n][0],dp[1][n][1])); return 0; }