题目:http://codeforces.com/contest/608/problem/D
题意:给定长度为n(n<=500)的序列s,你每次可以消除一个连续回文子序列,问最少多少次可以把串消完。
分析:
定义dp[L][R]代表区间[L,R]的最少消除次数。
1.当L==R时:dp[L][R]=1;
2.当L<R时,
--2.a) 当s[L]单独删掉,dp[L][R]=1+dp[L+1][R];
--2.b) 当s[L]作为回文串的一部分删掉时,那么s[L]==s[i],dp[L][R]=dp[L+1][i-1]+dp[i+1][R]。
3.当L>R时,dp[L][R]=1。此时区间的两个端点越过中点。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 1E9+9;
const int MI = ~0u>>1;
const int maxn = 555;
int dp[maxn][maxn],n,a[maxn];
int dfs(int L,int R)
{
if(L>R) return 1;
else if(L==R) return 1;
else
{
if(dp[L][R]!=INF) return dp[L][R];
else
{
dp[L][R]=1+dfs(L+1,R);
for(int i=L+1;i<=R;i++)
{
if(a[L]==a[i])
{
if(i!=R)
dp[L][R]=min(dp[L][R],dfs(L+1,i-1)+dfs(i+1,R));
else
dp[L][R]=min(dp[L][R],dfs(L+1,i-1));
}
}
}
}
return dp[L][R];
}
int main()
{
scanf("%d",&n);
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
dp[i][j]=INF;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
printf("%d\n",dfs(1,n));
return 0;
}