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
#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"<
 
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;
}

你可能感兴趣的:(Codeforces 1312 E. Array Shrinking (区间dp))