【CF-607B】Zuma 经典区间DP
B.Zuma
题意
给出一个长度为n的整数数组,每次可以去掉一个连续的回文子序列。
剩下的会靠拢,问最少几次可以去完。
题解
经典区间DP。
\(dp[i][j]\)表示把区间\([i,j]\)消除完的最小值
转移方程:
if arr[i]==arr[j]: dp[i][j]=dp[i+1][j-1]
dp[i][j]=min(dp[i][k],dp[k+1][j])
代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<math.h>
#define pb push_back
typedef long long ll;
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int N = 500+10;
int n,arr[N],dp[N][N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&arr[i]);
memset(dp,inf,sizeof(dp));
for(int i=1;i<=n;i++) dp[i][i]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;i+j-1<=n;j++)
{
int en=i+j-1;
if(arr[j]==arr[en])
{
if(j+1==en) dp[j][en]=1;
else dp[j][en]=dp[j+1][en-1];
}
for(int k=j;k<en;k++)
dp[j][en]=min(dp[j][en],dp[j][k]+dp[k+1][en]);
}
}
printf("%d\n",dp[1][n]);
return 0;
}
/*
*/