[CSP-S模拟测试]:军训队列(DP+乱搞)

Posted wzc521

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CSP-S模拟测试]:军训队列(DP+乱搞)相关的知识,希望对你有一定的参考价值。

题目描述

有$n$名学生参加军训,军训的一大重要内容就是走队列,而一个队列的不规整程度是该队中最高的学生的身高与最矮的学生的身高差值的平方。
现在要将$n$名参加军训的学生重新分成$k$个队列,每个队列的人数不限,请求出所有队列的不规整程度之和的最小值。


输入格式

第一行两个整数$n,k$,表示学生人数和队列数。
第二行$n$个实数,表示每名学生的身高。身高范围在$140sim 200cm$之间,保留两位小数。


输出格式

一个实数表示答案,保留$2$位小数。


样例

样例输入1:

3 2
170.00 180.00 168.00

样例输出1:

4.00

样例输入2:

5 2
170.00 180.00 168.00 140.59 199.99

样例输出2:

1023.36


数据范围与提示

技术图片


题解

$50$分的$DP$应该都会打,问题就在于如何优化。

的确可以斜率优化,但是考虑身高的范围,也就是说最多有$6000$种不同的身高。

那么离散化一下不就$AC$啦?

再考虑另一种并不正确的算法,尽可能让平方差最大的一组最小;的确是错的,第二个样例都过不了,但是在数据范围比较大的时候很难被卡;再结合前面暴力$DP$即可拿到满分……

时间复杂度:$Theta(6000 imes 6000)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,k;
double h[100001];
double dp[100001][21];
double ans=1000000000.0;
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)scanf("%lf",&h[i]);
	sort(h+1,h+n+1);
	n=unique(h+1,h+n+1)-h-1;
	for(int i=1;i<=n;i++)dp[i][1]=(h[i]-h[1])*(h[i]-h[1]);
	for(int j=2;j<=k;j++)
		for(int i=1;i<=n;i++)
		{
			dp[i][j]=10000000000.0;
			for(int l=i;l>=j;l--)
				dp[i][j]=min(dp[i][j],dp[l-1][j-1]+(h[i]-h[l])*(h[i]-h[l]));
		}
	printf("%.2lf",dp[n][min(n,k)]);
	return 0;
}

rp++

以上是关于[CSP-S模拟测试]:军训队列(DP+乱搞)的主要内容,如果未能解决你的问题,请参考以下文章

[CSP-S模拟测试]:小L的数(数位DP+模拟)

[CSP-S模拟测试]:花(DP)

[CSP-S模拟测试48]反思+题解

[CSP-S模拟测试]:折射(DP)

[CSP-S模拟测试]:蛇(DP+构造+哈希)

0922CSP-S模拟测试赛后总结