CodeForces

You are given a line of nn colored squares in a row, numbered from 11 to nn from left to right. The ii-th square initially has the color cici.

Let's say, that two squares ii and jj belong to the same connected component if ci=cjci=cj, and ci=ckci=ck for all kk satisfying i<k<ji<k<j. In other words, all squares on the segment from ii to jj should have the same color.

For example, the line [3,3,3][3,3,3] has 11 connected component, while the line [5,2,4,4][5,2,4,4] has 33 connected components.

The game "flood fill" is played on the given line as follows:

  • At the start of the game you pick any starting square (this is not counted as a turn).
  • Then, in each game turn, change the color of the connected component containing the starting square to any other color.

Find the minimum number of turns needed for the entire line to be changed into a single color.

Input

The first line contains a single integer nn (1n50001≤n≤5000) — the number of squares.

The second line contains integers c1,c2,,cnc1,c2,…,cn (1ci50001≤ci≤5000) — the initial colors of the squares.

Output

Print a single integer — the minimum number of the turns needed.

Input
4
5 2 2 1
Output
2
Input
8
4 5 2 2 1 3 5 5
Output
4
Input
1
4
Output
0

Note

In the first example, a possible way to achieve an optimal answer is to pick square with index 22 as the starting square and then play as follows:

  • [5,2,2,1][5,2,2,1]
  • [5,5,5,1][5,5,5,1]
  • [1,1,1,1][1,1,1,1]

In the second example, a possible way to achieve an optimal answer is to pick square with index 55 as the starting square and then perform recoloring into colors 2,3,5,42,3,5,4in that order.

In the third example, the line already consists of one color only.

区间规划:

区间dp,顾名思义就是在一段区间上进行动态规划。对于每段区间,他们的最优值都是由几段更小区间的最优值得到,是分治思想的一种应用,将一个区间问题不断划分为更小的区间直至一个元素组成的区间,枚举他们的组合 ,求合并后的最优值。

他的重点是一种从小区间向大区间扩展的过程。

算法结构

设F[i,j](1<=i<=j<=n)表示区间[i,j]内的数字相加的最小代价
每次用变量k(i<=k<=j-1)将区间分为[i,k]和[k+1,j]两段

For l:=2 to n do // 枚举区间长度
for i:=1 to n do // 枚举区间的左端点
begin
j:=i+l-1; // 计算区间的右端点,因为区间长度和左端点循环嵌套枚举,保证了[i,j]内的所有子区间都被枚举到
if j>n then break; // 保证了下标不越界
for k:= i to j-1 do // 状态转移,去推出 f[i,j]
f[i , j]= max{f[ i,k]+ f[k+1,j]+ w[i,j] }
end;

这个结构必须记好,这是区间动态规划的代码结构。

参考博文:https://www.jianshu.com/p/9c6401ea2f9b

此题AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define LLU unsigned long long
#define ZERO(a) memset(a, 0, sizeof(a))
const int maxn = 5e3 + 10;
int a[maxn];
LLU dp[maxn][maxn];
int x, y,cnt;

int main()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i ++)
    {
        cin >> x;
        if (x != y) a[++cnt] = x;
        y = x;
    }

    for(int len = 1; len < cnt; len++)
        for(int l = 1; l + len <= cnt; l++)
    {
        int r = l + len;
        if(a[l] == a[r])
            dp[l][r] = dp[l + 1][r - 1] + 1;
        else
            dp[l][r] = min(dp[l + 1][r] + 1, dp[l][r - 1] + 1);
    }

    cout << dp[1][cnt] <<endl;

}
原文地址:https://www.cnblogs.com/YY666/p/11240709.html