<题目链接>
题目大意:
一个由数字组成的序列,现在要消除这段序列,每次可以消去任意一段连续的回文数字,问最少消去几次能消完。
解题分析:
区间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]); }