标签:数学 namespace 连通 nbsp 其他 fine return test 一个
https://codeforces.com/contest/1114/problem/D
给一串数字,首先选择一个位置,类似于画图,然后每一轮按照以下步骤:
问最少几步可以把所有数字变成一样的
设dp[l][r][0/1]为把[l,r)范围变成和最左侧或最右侧数字一样需要的最少步数,
可以通过数学归纳证明
要注意的是有8种转移

$2\times2+2\times2$
其中有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\n", min(dp[0][n][0], dp[0][n][1]));
return 0;
}
标签:数学 namespace 连通 nbsp 其他 fine return test 一个
原文地址:https://www.cnblogs.com/sahdsg/p/12001195.html