CodeForces - 1312E Array Shrinking 区间dp

23 篇文章 0 订阅
2 篇文章 0 订阅

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

5
4 3 2 2 3

Output

2

Input

7
3 3 4 4 4 3 3

Output

2

Input

3
1 3 5

Output

3

Input

1
1000

Output

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.

区间dp

dp数组存l到r里面的个数

当相邻dp数组个数唯一且相等时更新

#include<bits/stdc++.h>
const int maxn = 1e3 + 5;
int num[maxn][maxn];
int dp[maxn][maxn];
using namespace std;

int main(){
	int n;
	cin >> n;
	for(int i = 1; i <= n; i++){
		cin >> num[i][i];
		dp[i][i] = 1;
	}
	for(int i = 1; i <= n; i++){
		for(int j = i; j <= n; j++){
			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++){
				dp[l][r] = min(dp[l][r], dp[l][k] + dp[k + 1][r]);
				if(dp[l][k] == 1 && dp[k + 1][r] == 1 && num[l][k] == num[k + 1][r]){
					dp[l][r] = 1;
					num[l][r] = num[l][k] + 1;					
				}
			}
		}
	}
	cout << dp[1][n] << endl;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值