我们发现一个很有趣的性质:假设且,先把区间中的回文串消到只剩一个,这一个回文串会和两段的构成一个更大的回文串,所以在消去这个回文串的同时,顺便消掉两端的和即可。
考虑如下的方程,为把全部消完最小的花费。
,为上面讨论过的情况,直接即可
考虑在中间设一个分割点,发现
边界条件,这里我们把设为(长度为的回文串),把设为(长度为的回文串)
代码最好用记忆化搜索实现,看起来清晰一点:
#include <bits/stdc++.h>
#define MAXN 505
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=(x<<3)+(x<<1)+(ch^'0');
ch=getchar();
}
return x*f;
}
int dp[MAXN][MAXN],a[MAXN],n;
int dfs(int l,int r){
if (dp[l][r]!=0x3f3f3f3f) return dp[l][r];
if (l==r||l==r+1) return 1;
if (a[l]==a[r]) dp[l][r]=dfs(l+1,r-1);
for (register int i=l;i<r;++i){
dp[l][r]=min(dp[l][r],dfs(l,i)+dfs(i+1,r));
}
return dp[l][r];
}
int main(){
n=read();
for (register int i=1;i<=n;++i){
a[i]=read();
}
memset(dp,0x3f,sizeof(dp));
printf("%d\n",dfs(1,n));
}