CodeForces - 1312E Array Shrinking (區間dp)

Array Shrinking

題目描述

You are given an array a1,a2,…,an. You can perform the following operation any number of times:
Choose a pair of two neighboring equal elements ai=ai+1 (if there is at least one such pair).
Replace them by one element with value ai+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 a you can get?

Input
The first line contains the single integer n (1≤n≤500) — the initial length of the array a.

The second line contains n integers a1,a2,…,an (1≤ai≤1000) — the initial array a.

Output

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

Examples

Input #1
5
4 3 2 2 3

Output #1
2

Input #2
7
3 3 4 4 4 3 3

Output #2
2

Input #3
3
1 3 5

Output #2
3

Input #4
1
1000

Output #4
1

Solution

區間dp.O(n^3)
令dp[i][j]表示從i到j區間進行合併後的最短長度。
dp[i][j] = dp[i][k] + dp[k + 1][j],
如果dp[i][k] 和 dp[k+1][j]都僅有一個數字且相同,那麼他們兩個可以合併,進行合併。
需要記錄一下i和j合併成一個數字後,該數字爲幾,comm[i][j]即爲i到j合併爲的一個數字。
轉移順序,區間dp的轉移方法,枚舉區間長度和左端點,算出右端點,枚舉斷點k。

答案爲dp[1][n]。

代碼

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;

typedef long long ll;

const int INF = 0x3f3f3f3f;
const int SZ = 500 + 20;

int n,dp[SZ][SZ],comm[SZ][SZ],num[SZ];

int main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++ )
    {
        scanf("%d",&num[i]);
        dp[i][i] = 1; //初始化
        comm[i][i] = num[i];
    }
    for(int len = 2;len <= n;len ++ )
    {
        for(int i = 1;i <= n - len + 1;i ++ )
        {
            int j = i + len - 1;
            dp[i][j] = INF;
            for(int k = i;k <= j - 1;k ++ )
            {
                if(dp[i][j] >= dp[i][k] + dp[k + 1][j])
                {
                    dp[i][j] = dp[i][k] + dp[k + 1][j]; //狀態轉移
                    if(dp[i][k] == 1 && dp[k + 1][j] == 1 && comm[i][k] == comm[k + 1][j]) //合併
                    {
                        dp[i][j] = 1;
                        comm[i][j] = comm[i][k] + 1;
                    }
                }
            }
        }
    }
    printf("%d",dp[1][n]);
    //system("pause");
    return 0;
}

2020.3.17

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章