區間dp - codeforces

 題意 :

  給你 n 個數字,相鄰的數字若是相同,則表明他們是一個塊的,每次操做能夠將一個塊的數字變成任意一種數字,求最小操做次數,將整個區間的全部數字變成相同的blog

思路分析 :

  定義 dp[i][j][k]  k = 0 / 1 , dp[i][j][0] 表示將區間變成和左邊數字同樣的最小操做次數, dp[i][j][1] 表示將區間變成和右邊數字同樣的最小操做次數 , 而後就是正常的方程轉移了ci

代碼示例 :

int n;
int a[5005];
int dp[5005][5005][2];

void solve(){
    for(int i = 1; i <= n; i++){
        for(int j = i; j <= n; j++){
            dp[i][j][0] = dp[i][j][1] = (i==j?0:inf);
        }
    }
    
    for(int len = 2; len <= n; len++){
        for(int i = 1; i <= n; i++){
            int j = i+len-1;
            if (j > n) break;
            
            if (i < n) {
                dp[i][j][0] = min(dp[i][j][0], dp[i+1][j][0]+(a[i]!=a[i+1]));
                dp[i][j][0] = min(dp[i][j][0], dp[i+1][j][1]+(a[i]!=a[j]));
            
            }
            if (j > 1) {
                dp[i][j][1] = min(dp[i][j][1], dp[i][j-1][0]+(a[i]!=a[j]));
                dp[i][j][1] = min(dp[i][j][1], dp[i][j-1][1]+(a[j-1]!=a[j]));
            }
        }
    }
    cout << min(dp[1][n][0], dp[1][n][1]) << endl;
}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    solve();
    return 0;
}
相關文章
相關標籤/搜索