题目链接
题意:你可以删除一个回文序列,问你最少操作几次能删完。
思路:这里提供两个思路,一个是常见的枚举区间,第二个是记忆化,dp【l】【r】代表区间【l,r】删完的最少次数。
枚举区间:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,dp[501][501],a[501];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[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(l+1==r) dp[l][r]=((a[l]==a[r])?1:2);
for(int k=l;k<r;++k)
dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);
if(a[l]==a[r]) dp[l][r]=min(dp[l][r],dp[l+1][r-1]);
}
}
printf("%d\n",dp[1][n]);
}
记忆化:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,dp[501][501],a[501];
const int inf=0x3f3f3f3f;
int dfs(int l,int r)
{
if(l==r) return dp[l][r]=1;
if(l>r) return 1;
if(dp[l][r]!=inf) return dp[l][r];
int ans=inf;
if(a[l]==a[r]) ans=min(ans,dfs(l+1,r-1));
for(int k=l;k<r;++k)
ans=min(ans,dfs(l,k)+dfs(k+1,r));
return dp[l][r]=ans;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
memset(dp,inf,sizeof(dp));
printf("%d\n",dfs(1,n));
}