zoukankan      html  css  js  c++  java
  • [Educational Codeforces Round 83 ] E. Array Shrinking

    [Educational Codeforces Round 83 ] E. Array Shrinking - (区间DP)

    E. Array Shrinking

    time limit per test

    2 seconds

    memory limit per test

    256 megabytes

    input

    standard input

    output

    standard output

    You are given an array a1,a2,…,ana1,a2,…,an. You can perform the following operation any number of times:

    • Choose a pair of two neighboring equal elements ai=ai+1ai=ai+1 (if there is at least one such pair).
    • Replace them by one element with value ai+1ai+1.

    After each such operation, the length of the array will decrease by one (and elements are renumerated accordingly). What is the minimum possible length of the array aa you can get?

    Input

    The first line contains the single integer nn (1≤n≤5001≤n≤500) — the initial length of the array aa.

    The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤10001≤ai≤1000) — the initial array aa.

    Output

    Print the only integer — the minimum possible length you can get after performing the operation described above any number of times.

    Examples

    input

    Copy

    5
    4 3 2 2 3
    

    output

    Copy

    2
    

    input

    Copy

    7
    3 3 4 4 4 3 3
    

    output

    Copy

    2
    

    input

    Copy

    3
    1 3 5
    

    output

    Copy

    3
    

    input

    Copy

    1
    1000
    

    output

    Copy

    1
    

    Note

    In the first test, this is one of the optimal sequences of operations: 44 33 22 22 33 →→ 44 33 33 33 →→ 44 44 33 →→ 55 33.

    In the second test, this is one of the optimal sequences of operations: 33 33 44 44 44 33 33 →→ 44 44 44 44 33 33 →→ 44 44 44 44 44 →→ 55 44 44 44 →→ 55 55 44 →→ 66 44.

    In the third and fourth tests, you can't perform the operation at all.

    题意:

    给定一个含有n个整数的数组,你可以将两个相邻且相等的数(X)合并成一个(X+1),其他的数位置和数值都不变,问当你在最优操作的情况下,最少能剩下多少个元素?

    思路:

    数据范围考虑用区间DP,

    定义状态:(dp[i][j])表示数组(a_i,a_{i+1},dots,a_{j}) 可以合并的最短长度。

    辅助数组:(b[i][j])表示数组(a_i,a_{i+1},dots,a_{j}) 可以合并的最短长度时的数值。

    转移:

    不合并时:

    枚举区间([i,j])中的k,(dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]))

    合并元素时:

    (dp[i][k] = 1 , dp[k + 1][j] = 1 , b[i][k] = b[k + 1][j])(dp[i][j] = 1,b[i][j] = b[i][k] + 1)

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #include <sstream>
    #include <bitset>
    #define ALL(x) (x).begin(), (x).end()
    #define sz(a) int(a.size())
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    #define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
    #define du2(a,b) scanf("%d %d",&(a),&(b))
    #define du1(a) scanf("%d",&(a));
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
    ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;}
    void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
    inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
    const int maxn = 510;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    int n;
    int a[maxn];
    int b[maxn][maxn];
    int dp[maxn][maxn];
    int main()
    {
        //freopen("D:\code\text\input.txt","r",stdin);
        //freopen("D:\code\text\output.txt","w",stdout);
        n = readint();
        repd(i, 1, n)
        {
            a[i] = readint();
            b[i][i] = a[i];
        }
        repd(i, 1, n)
        {
            repd(j, i, n)
            {
                dp[i][j] = j - i + 1;
            }
        }
        repd(len, 2, n)
        {
            repd(i, 1, n - len + 1)
            {
                int j = i + len - 1;
                repd(k, i, i + len - 2)
                {
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);
                    if (dp[i][k] == 1 && dp[k + 1][j] == 1 && (b[i][k] == b[k + 1][j]))
                    {
                        dp[i][j] = 1;
                        b[i][j] = b[i][k] + 1;
                    }
                }
            }
        }
        printf("%d
    ", dp[1][n] );
        return 0;
    }
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    下载vue-devtools插件的步骤
    弄清 CSS3 的 transition 和 animation
    js与多行字符串
    swift 上手
    liunux 修改hostname
    linux 下使用配置文件
    linux安装oracle11g
    jQueryt过滤选择器
    Javascript并发模型和事件循环
    CSS生僻问题一网打尽
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/12459286.html
Copyright © 2011-2022 走看看