CF1114D Flood Fill (#區間dp)

題目描述

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 c_ici​ .

Let's say, that two squares ii and jj belong to the same connected component if c_i = c_jci​=cj​ , and c_i = c_kci​=ck​ for all kk satisfying i < k < ji<k<j . In other words, all squares on the segment from ii to jjshould 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 33connected 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.

輸入格式

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

The second line contains integers c_1, c_2, \ldots, c_nc1​,c2​,…,cn​ ( 1 \le c_i \le 50001≤ci​≤5000 ) — the initial colors of the squares.

輸出格式

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

題意翻譯

nn 個方塊排成一排,第 ii 個顏色爲 c_ici​。定義一個顏色聯通塊 [l,r][l,r] 當且僅當 ll 和 rr 之間(包括 l,rl,r)所有方塊的顏色相同。現在你可以選定一個起始位置 pp,每次將 pp 所在顏色聯通塊的所有方塊顏色改成另一種。這個操作可能將多個顏色聯通塊合併成一個。問最少要多少步,能讓 [1,n][1,n] 變成一個顏色聯通塊。

1\le n,c_i\le 50001≤n,ci​≤5000。

輸入輸出樣例

輸入 #1複製

4
5 2 2 1

輸出 #1複製

2

輸入 #2複製

8
4 5 2 2 1 3 5 5

輸出 #2複製

4

輸入 #3複製

1
4

輸出 #3複製

0

思路

區間dp。因爲p所在的顏色聯通塊就是一個區間。這個區間只會往外擴張,不會往裏收縮。

首先先把連通塊壓成一塊,不影響答案。壓縮後長度爲cnt。

令dp[i][j]爲區間[i,j]是最長連通塊,且不被其他連通塊包含,將[1,cnt]變爲連通塊的最小步數。

如果a[i]=a[j],也就是兩邊顏色相同

dp[i][j]=dp[i+1][j-1]+1

因爲是合併,步數+1。

如果a[i]≠a[j],那就兩邊分別取最優即可。

dp[i][j]=min(dp[i+1][j],dp[i][j-1])+1

#include <stdio.h>
#include <iostream>
#define N 5001
using namespace std;
int n,s,cnt,a[N],dp[N][N],x,y;
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i,j,k,l;
	cin>>n;
	for(i=1;i<=n;i++)//壓縮連通塊 
	{
		cin>>x;
		if(x!=y)
		{
			a[++cnt]=x;
		}
		y=x;
	}
	for(l=1;l<=cnt;l++)
	{
		for(i=1;i<=cnt;i++)
		{
			j=i+l;
			if(a[i]==a[j])
			{
				dp[i][j]=dp[i+1][j-1]+1;
			}
			else
			{
				dp[i][j]=min(dp[i+1][j],dp[i][j-1])+1;
			}
		}
	}
	cout<<dp[1][cnt]<<endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章