您的位置:首页 > 其它

codeforces #336 D. Zuma (区间dp)

2016-02-22 21:17 423 查看
题目: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  区间dp