看题解前毫无思路,看完之后怎么这么傻逼一题。自己还是太菜了。
考虑dp[l][r]为l-r区间内合并完剩的最小个数。那么考虑只有两个相邻区间都能合并成一个相同数字的情况,才能对合并结果有影响,要不然两个区间内的个数直接相加即可。
此时还需一个a数组记录l,r合并成的一个数字时的值。
//#pragma GCC optimize("-Ofast","-funroll-all-loops") //#pragma GCC optimize(2) //freopen("C://std/a.in","r",stdin); //freopen("C://std/b.txt","w",stdout); #include<bits/stdc++.h> #define ll long long #define PB push_back #define endl ' ' #define INF 0x3f3f3f3f #define LINF 0x3f3f3f3f3f3f3f3f #define ull unsigned long long #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r #define lowbit(x) (x & (-x)) #define rep(i, a, b) for(register int i = a ; i <= b ; ++ i) #define per(i, a, b) for(register int i = b ; i >= a ; -- i) #define clr(a, b) memset(a, b, sizeof(a)) #define in insert #define random(x) (rand()%x) #define PII(x, y) make_pair(x, y) #define fi first #define se second #define pi acos(-1) #define re register //std::ios::sync_with_stdio(false); using namespace std; const int maxn = 500 + 50; const ll mod = 1e9 + 7; int n; int a[maxn][maxn], dp[maxn][maxn]; signed main(){ cin >> n; rep(i, 1, n) scanf("%d", &a[i][i]); rep(i, 1, n) rep(j, i, n) dp[i][j] = j - i + 1; for(int len = 2 ; len <= n ; ++ len){ for(int l = 1 ; l + len - 1 <= n ; ++ l){ int r = l + len - 1; for(int k = l ; k < r ; ++ k){ if(dp[l][k]==1&&dp[k+1][r]==1&&a[l][k]==a[k+1][r]){ dp[l][r] = 1; a[l][r] = a[l][k] + 1; } else{ dp[l][r] = min(dp[l][r], dp[l][k] + dp[k+1][r]); } } } } cout << dp[1][n]; return 0; }