CF1312E Array Shrinking's Solution

C C A

2020-03-11 12:54:18

Solution

# $CF1312E\ Array\ Shrinking's\ Solution$ $\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad\qquad By$ [$CCA$](https://www.luogu.com.cn/user/78645) ## $Problem$ $\qquad$给定一个数组,定义一次合并为对于两个相邻的数,如果他们相等,则可以将它们合并为一个数,其值为原数$+1$(参照$2048$)。问原数组合并完后的最小长度。 ## $Solution$ $\qquad$这题十分套路。 $\qquad$我们考虑区间$DP$,令$dp[l][r]$表示$l$到$r$这段区间合并后的最小长度,同时,我们需要一个$w$数组来辅助计算,$w[l][r]$表示按照$dp[l][r]$合并完后,$l$到$r$这段区间的和是多少,转移很显然: $$dp[l][r] = min\{dp[l][mid] + dp[mid + 1][r]\}$$ 如果$dp[l][mid]=dp[mid + 1][r]=1$,并且$w[l][mid]=w[mid + 1][r]$,则: $$dp[l][r] = 1 , w[l][r] = w[l][mid] + 1$$ ## Code ```cpp #include<bits/stdc++.h> using namespace std; const int N = 500 + 10; int n , a[N] , dp[N][N] , w[N][N]; int main(){ memset(dp , 63 , sizeof(dp)); scanf("%d" , &n); for(int i = 1; i <= n; i++) scanf("%d" , &a[i]) , dp[i][i] = 1 , w[i][i] = a[i]; for(int k = 2; k <= n; k++) for(int l = 1; l + k - 1 <= n; l++){ int r = l + k - 1; for(int mid = l; mid < r; mid++){ dp[l][r] = min(dp[l][r] , dp[l][mid] + dp[mid + 1][r]); if(dp[l][mid] == dp[mid + 1][r] && dp[l][mid] == 1 && w[l][mid] == w[mid + 1][r]) dp[l][r] = 1 , w[l][r] = w[l][mid] + 1; } } printf("%d" , dp[1][n]); return 0; } ``` 自认为码风还是比较清奇可看的,大家可以对着$Solution$仔细看一下。 最后,[$This\ is\ my\ blog$](https://www.luogu.com.cn/blog/A66-888/) , 有兴趣的可以逛一下,应该能有所收获。