CF 1114D(538,div2) Flood Fill

https://codeforces.com/contest/1114/problem/D

题目

给一串数字,首先选择一个位置,类似于画图,然后每一轮按照以下步骤:

  • 可以将这个位置所在的连通块改成其他数字

问最少几步可以把所有数字变成一样的

题解

设dp[l][r][0/1]为把[l,r)范围变成和最左侧或最右侧数字一样需要的最少步数,

可以通过数学归纳证明

  • 选择什么数字不重要,即使选择是中间的数字,步数一样不会变小

要注意的是有8种转移

 $2 imes2+2 imes2$

其中有4种转移肯定不是最优,因为选择的点的位置不能变。

AC代码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 5007
int c[MAXN];
int dp[MAXN][MAXN][2];
int main() {
	int n; scanf("%d", &n);
	for(int i=0; i<n; i++) {
		scanf("%d", &c[i]);
	}
	for(int i=0; i<n; i++) {
		dp[i][i][0]=dp[i][i][1]=dp[i][i+1][0]=dp[i][i+1][1]=0;
	}
	for(int d=2; d<=n; d++) {
		for(int l=0; l+d<=n; l++) {
			int r=l+d;
			dp[l][r][0]=dp[l][r][1]=0x3f3f3f3f;
			const int cs[][2]={{l+1, r-1},{l, r-2}};
			for(int k=0; k<2; k++) {
				dp[l][r][0] = min(dp[l][r][0], dp[l+1][r][k]+int(c[cs[0][k]]!=c[l]));
				dp[l][r][1] = min(dp[l][r][1], dp[l][r-1][k]+int(c[cs[1][k]]!=c[r-1]));
			}
		}
	}
	printf("%d
", min(dp[0][n][0], dp[0][n][1]));
	return 0;
}
 
原文地址:https://www.cnblogs.com/sahdsg/p/12001195.html