cf : Array Shrinking【dp】

题目大意

给定一个长度为n的数组,相邻的两个数字如果相同就可以合并成一个比他们大一的数字,
问:最后可以达到的最短的数组长度为多少

样例

input
5
4 3 2 2 3
output
2
样例解释:
34位的2合并成 3 --> 4 3 3 3 
2 3号位的合并成4 --> 4 4 3
1 2 号位4合并成5 --> 5 3
答案就是 2

思路
用二维数组将数组在对角线位置存起来

4 0 0 0 0
0 3 0 0 0
0 0 2 0 0
0 0 0 2 0
0 0 0 0 3

通过合并操作就可以得到如下数组

4 0 0 5 0
0 3 0 4 0
0 0 2 3 4
0 0 0 2 0
0 0 0 0 3

转换过程

最后通过cost数组模拟转换过程,如最后的3由左上角的2+1,而2是由cost[0]+1, 因为他的最上面5这个位置不是0, 代表它可以合并3次,就剩她1一个,所以到他为止的长度为1.

代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 520;
int n, a[N][N], f[N];
int cost[500], dp[500][500];
int main()
{
	scanf("%d", &n);
	memset(dp, -1, sizeof dp);
	for (int i = 0; i < n; i++)
		scanf("%d", &dp[i][i]);

	for(int len = 2; len <= n; len++)
	{
		for(int left = 0; left + len - 1 < n; left++)
		{
			int right = left + len - 1;
			for(int t = left; t < right; t++)
			{
				if(dp[left][t] == dp[t + 1][right] && dp[left][t] != -1)
				dp[left][right] = dp[left][t] + 1;
			}
		}
	}

	cost[0] = 0;
	for(int i = 1; i <= n; i++)
	{
		cost[i] = 0x3f3f3f3f;
		for(int j = 0; j < i; j++)
		{
			if(dp[j][i - 1] != -1)
			{
				cost[i] = min(cost[i], cost[j] + 1);
			}
		}
	}
	printf("%d\n", cost[n]);
}
发布了110 篇原创文章 · 获赞 214 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_45432665/article/details/104792985