区间dp - codeforces
题意 :
给你 n 个数字,相邻的数字如果相同,则代表他们是一个块的,每次操作可以将一个块的数字变成任意一种数字,求最小操作次数,将整个区间的所有数字变成相同的
思路分析 :
定义 dp[i][j][k] k = 0 / 1 , dp[i][j][0] 表示将区间变成和左边数字一样的最小操作次数, dp[i][j][1] 表示将区间变成和右边数字一样的最小操作次数 , 然后就是正常的方程转移了
代码示例 :
int n; int a[5005]; int dp[5005][5005][2]; void solve(){ for(int i = 1; i <= n; i++){ for(int j = i; j <= n; j++){ dp[i][j][0] = dp[i][j][1] = (i==j?0:inf); } } for(int len = 2; len <= n; len++){ for(int i = 1; i <= n; i++){ int j = i+len-1; if (j > n) break; if (i < n) { dp[i][j][0] = min(dp[i][j][0], dp[i+1][j][0]+(a[i]!=a[i+1])); dp[i][j][0] = min(dp[i][j][0], dp[i+1][j][1]+(a[i]!=a[j])); } if (j > 1) { dp[i][j][1] = min(dp[i][j][1], dp[i][j-1][0]+(a[i]!=a[j])); dp[i][j][1] = min(dp[i][j][1], dp[i][j-1][1]+(a[j-1]!=a[j])); } } } cout << min(dp[1][n][0], dp[1][n][1]) << endl; } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); cin >> n; for(int i = 1; i <= n; i++) cin >> a[i]; solve(); return 0; }
东北日出西边雨 道是无情却有情