给了一组数,每次可以选择两个相邻且相等的数x替换为x+1,问最后能得到的最少的数的个数
区间dp:
dp[i][j]表示区间[i,i+1..j]能得到的最少数的个数,f[i][j]表示对应的值是多少,转移方程如下
dp[i][j] =min(dp[i][j], dp[i][k] + dp[k+1][j])
if (dp[i][k] == 1 && dp[k+1][j] == 1 && f[i][k] == f[k+1][j]) {
dp[i][j] = 1;
f[i][j] = f[i][k] + 1;
}
const int maxn = 555;
int n, a[maxn], dp[maxn][maxn], f[maxn][maxn];
int main() {
ios::sync_with_stdio (false);
cin.tie (0);
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
CLR(dp, 0x7f);
for (int i = 1; i <= n ; i++) {
dp[i][i] = 1;
f[i][i] = a[i];
}
for (int len = 2; len <= n; len++) {
for (int i = 1; i + len - 1 <= n; i++) {
int j = i + len - 1;
for (int k = i; k < j; k++) {
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]);
if (dp[i][k] == 1 && dp[k+1][j] == 1 && f[i][k] == f[k+1][j]) {
dp[i][j] = 1;
f[i][j] = f[i][k] + 1;
}
}
}
}
cout << dp[1][n] << endl;
return 0;
}