欢乐赛F

HDU1421
原题链接https://vjudge.net/contest/350953#problem/F
在这里插入图片描述
运用动态规划来解题,由于相邻的数的差值肯定较小,所以我们应该先排序,dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+(a[i-1]-a[i])*(a[i-1]-a[i])),对于每个j比较出相邻两个数中应该选哪一个
附一组数据
input:
7 3
7 9 4 3 1 9 2
output:
2
在这里插入图片描述
具体情况可以删去下方代码注释来一点一点分析。
第一列将前n项没两项的差值的最小值计算出来,
第二列从第4位开始 3 4 位加上前两位的最小值;
第5位加上前三位的最小值,再与上一个比较出大小,就求出了前5位取4个数的最小值,以此类推,
第三列从第5项开始,前四项的取四项的最小值加上5 6位,以及前六位的最小值加上6 7 位再与前者进行比较,较小的数即为答案。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
long long a[20005];
long long dp[2005][2005];
int main()
{
	long long n, k;
	while (~scanf("%lld %lld", &n, &k))
	{
		memset(a, 0, sizeof(a));
		long long i, j;
		for (i = 0; i < n; i++)
		{
			scanf("%lld", &a[i]);
		}
		for (i = 0; i < n; i++)
		{
			for (j = 0; j <= k; j++)
			{
				if (j == 0)
				{
					dp[i][j] = 0;
				}
				else
				{
					dp[i][j] = 1e9;//dp给一个初始值,如果要分析可以改为100;
				}
			}
		}
		sort(a, a + n);
		for (i = 2; i <= n; i++)
		{
			for (j = 1; j <= k && j <= i; j++)
			{
				dp[i][j] = min(dp[i - 2][j - 1] + (a[i - 1] - a[i - 2]) * (a[i - 1] - a[i - 2]), dp[i - 1][j]);
			//	for (int iii = 0; iii < n; iii++)
			//	{
			//		cout << a[iii] << " ";
			//	}
			//	cout << endl;
			//	for (int ii = 0; ii <= n; ii++)
			//	{
			//		cout << a[ii] << " ";
			//		for (int jj = 0; jj <= k; jj++)
			//		{
			//			printf("%4lld", dp[ii][jj]);
			//		}
			//		cout << endl;
			//	}
			//	cout << "**************" << endl;
			}
		//	cout << "换行" << endl;
		}
		printf("%lld\n", dp[n][k]);
	}
	return 0;
}
发布了130 篇原创文章 · 获赞 3 · 访问量 1600

猜你喜欢

转载自blog.csdn.net/yeyuluo/article/details/103961950
今日推荐