Codeforces 607B Zuma (区间DP)

<题目链接>

题目大意:

一个由数字组成的序列,现在要消除这段序列,每次可以消去任意一段连续的回文数字,问最少消去几次能消完。

解题分析:
区间DP,$dp[i][j]$表示消除这段区间所有数字的最小次数,首先对那些长度为1的区间进行预处理,因为长度为1一定能够1次消除,所以$dp[i][i]=1$,其次,对于$[l,r]$区间,当$arr[l]==arr[r]$时,$dp[l][r]$能够由$dp[l+1][r-1]$转移而来(区间长度为2的时候特判一下)。

#include <bits/stdc++.h>
using namespace std;

#define N 505
int n,arr[N],dp[N][N];

int main(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&arr[i]);
    memset(dp,0x3f,sizeof(dp));     
    for(int i=1;i<=n;i++)dp[i][i]=1;     
    for(int len=2;len<=n;len++){
        for(int l=1;l+len-1<=n;l++){
            int r=l+len-1;
            if(arr[l]==arr[r]&&len>2)dp[l][r]=dp[l+1][r-1];
            else if(arr[l]==arr[r])dp[l][r]=1;   //因为我们对于arr[l]==arr[r]的情况,是从 [l+1,r-1]转移而来,所以这里我们需要特判一下区间长度为2的情况
            for(int k=l;k<r;k++)
                dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);

        }
    }
    printf("%d
",dp[1][n]);
}
原文地址:https://www.cnblogs.com/00isok/p/10637968.html