E - Array Shrinking,区间dp,Educational Codeforces Round 83 (Rated for Div. 2)

E - Array Shrinking,Educational Codeforces Round 83 (Rated for Div. 2)

http://codeforces.com/contest/1312/problem/E
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?
思路:首先令 d p [ i ] [ j ] dp[i][j] dp[i][j]为i ~ j能够合并成的最少数字, a [ i ] [ j ] a[i][j] a[i][j]表示i ~ j能够合并成一个数字时对应的数字,直接类似区间dp,枚举分割点k将这个区间分为两段分别计算dp值,然后将它们合并,不用考虑合并时前一段区间的右侧和后一段区间的左侧可以继续合并,因为这中情况会在枚举其他k的时候考虑到

#include
#define MAXN 5005
#define INF 0x3f3f3f3f
using namespace std;
int dp[MAXN][MAXN],a[MAXN][MAXN],n;
inline int solve(int l,int r)
{
	if(dp[l][r] != INF)
		return dp[l][r];
	int ans = INF;
	for(int k = l;k < r;++k)
	{
		int t1 = solve(l,k),t2 = solve(k+1,r);
		if(t1 + t2 <= ans)
		{
			ans = t1 + t2;
			if(t1 == 1 && t2 == 1 && a[l][k] == a[k+1][r])
			{
				ans = 1;
				a[l][r] = a[l][k]+1;
			}
		}
	}
	dp[l][r] = ans;
	return ans;
}
int main()
{
	while(~scanf("%d",&n))
	{
		memset(dp,0x3f,sizeof(dp));
		for(int i = 1;i <= n;++i)
		{
			scanf("%d",&a[i][i]);
			dp[i][i] = 1;
		}
		printf("%d\n",solve(1,n));
	}
	return 0;
}

你可能感兴趣的:(DP)