cf 607b
题意
给定一个序列,每次操作可以消除一个回文子串,求最少多少次可以消除整个序列
思路
明显dp,设状态 dp[i][j] 表示 [i , j] 这个区间需要消除的最小次数
那么易得 dp[i][i] = 1(长度为 1)
那么当长度为 2 时,dp[i][i + 1] = (s[i] = = s[i + 1] ? 1 : 2)
枚举区间长度,每次枚举开头
设当前枚举区间长为 n
如果 s[i] = = s[i + n - 1] 则有 dp[i][i + n - 1] = dp[i + 1][i + n - 2]
否则有 dp[i][i + n - 1] = min(dp[i][i + n - 1] , dp[i][k] + dp[i][k - 1])
复杂度分析
时间复杂度:O(n3)
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int s[N];
int dp[N][N];
int main()
{
int n;
scanf("%d" , &n);
for(int i = 1 ; i <= n ; i++)
{
scanf("%d" , &s[i]);
}
for(int i = 1 ; i <= n ; i++)
{
dp[i][i] = 1;
if(i == n)
{
continue;
}
dp[i][i + 1] = (s[i] == s[i + 1] ? 1 : 2);
}
for(int l = 3 ; l <= n ; l++)
{
for(int i = 1 ; i + l - 1 <= n ; i++)
{
dp[i][i + l - 1] = 1e9;
if(s[i] == s[i + l - 1])
{
dp[i][i + l - 1] = dp[i + 1][i + l - 2];
}
for(int j = i ; j < i + l - 1 ; j++)
{
dp[i][i + l - 1] = min(dp[i][i + l - 1] , dp[i][j] + dp[j + 1][i + l - 1]);
}
}
}
printf("%d" , dp[1][n]);
return 0;
}