E. Array Shrinking(区间dp)

看题解前毫无思路,看完之后怎么这么傻逼一题。自己还是太菜了。

考虑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 '\n'
#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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Ketchum/p/13385746.html