标签:数学 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