Codeforces 1312 E. Array Shrinking (區間dp)

E. Array Shrinking
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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
inputCopy
5
4 3 2 2 3
outputCopy
2
inputCopy
7
3 3 4 4 4 3 3
outputCopy
2
inputCopy
3
1 3 5
outputCopy
3
inputCopy
1
1000
outputCopy
1
Note
In the first test, this is one of the optimal sequences of operations: 4 3 2 2 3 → 4 3 3 3 → 4 4 3 → 5 3.

In the second test, this is one of the optimal sequences of operations: 3 3 4 4 4 3 3 → 4 4 4 4 3 3 → 4 4 4 4 4 → 5 4 4 4 → 5 5 4 → 6 4.

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

題意:
跟2048類似,相同的兩個x可以合併成x+1,給一個序列,問最後最少能剩下多少個元素。

思路:

  1. 首先數據才500,很明顯的區間dp數據。
  2. 考慮之前區間dp[1][n]作爲答案,那麼dp數組很明顯爲 i 到 j 最後剩下多少個元素,那麼還需要另外用一個數組a來表示 i 到 j 合併出來的數字。
  3. 先預處理dp[i][j]的元素個數爲j-i+1,dp[i][i]=1。
  4. 然後就是常規區間dp了,枚舉區間長度,區間起點和區間終點。
  5. 只有當左區間和右區間的長度爲1且左右區間各自合併出來的數字相等時纔可以合併,即dp[l][k]==1&&dp[k+1][r]==1&&a[l][k]==a[k+1][r]。
  6. 如果有什麼講的不清楚的地方歡迎提出來,歡迎交流~

代碼:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define ins insert
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#pragma GCC optimize(2)
using namespace std;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }ll qpf(ll a, ll b, ll p){ll ret = 0;while(b)
{if(b & 1) ret = (ret + a) % p;a = (a + a) % p;b >>= 1;}return ret % p ;}
ll qp(ll a, ll n, ll p){ll ret = 1;while(n){if(n & 1) ret = qpf(ret, a, p);
a = qpf(a, a, p);n >>= 1;}return ret % p ;}//��=acos(L/2R);
//void debug1(){ cout<<"I CAN AC"<<endl;}//void debug2(){printf("T A T\n");}
 
const int manx=1e3+5;
 
ll dp[manx][manx],a[manx][manx];
 
int main()
{
    ll n=read();
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            dp[i][j]=j-i+1;
    for(int i=1;i<=n;i++)
        a[i][i]=read(),dp[i][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++){
                dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]);
                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;
            }
        }
    printf("%lld",dp[1][n]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章