18.03.25 vijos1061迎春舞会之三人组舞

背景

HNSDFZ的同学们为了庆祝春节,准备排练一场舞

描述

n个人选出3*m人,排成m组,每组3人。

站的队形——较矮的2个人站两侧,最高的站中间。

从对称学角度来欣赏,左右两个人的身高越接近,则这一组的“残疾程度”越低。

计算公式为 h=(a-b)^2 (a、b为较矮的2人的身高)
那么问题来了。

现在候选人有n个人,要从他们当中选出3*m个人排舞蹈,要求总体的“残疾程度”最低。

格式

输入格式

第一排为m,n。

第二排n个数字,保证升序排列。

输出格式

输出最小“残疾程度”。

样例1

样例输入1

9 40
1 8 10 16 19 22 27 33 36 40 47 52 56 61 63 71 72 75 81 81 84 88 96 98 103 110 113 118 124 128 129 134 134 139 148 157 157 160 162 164
Copy样例输出1
23

限制

各个测试点1s

提示

m<=1000,n<=5000
数据保证3*m<=n

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <stdlib.h>
 4 #include <cstdio>
 5 #include <memory.h>
 6 
 7 using namespace std;
 8 const int maxn=5005;
 9 int f[maxn][1005];
10 
11 int main()
12 {
13     memset(f,0x37,sizeof(f));
14     int m,n;//m groups n stus
15     scanf("%d%d",&m,&n);
16     int st[maxn];
17     for(int i=1;i<=n;i++){
18         scanf("%d",&st[i]);
19         f[i][0]=0;}
20     for(int i=n-2;i>=1;i--)
21         for(int j=1;j<=min(m,(n-i+1)/3);j++){
22             f[i][j]=min(f[i+1][j],f[i+2][j-1]+(st[i]-st[i+1])*(st[i]-st[i+1]));
23         }
24     printf("%d
",f[1][m]);
25     return 0;
26 }
View Code

状态转移方程:f[x][y]记录最高的那x人里分y组时最小残疾值

f[x][y]=min{f[x+1][y],f[x+2][y-1]}

倒序处理是为了保证下一个人一定是一组中站在两边的(比较矮)

防止出现凑齐了俩人却没有高个子补上的尴尬情况

正序的话就变成加的那个人肯定是高个了 组的情况就不那么明确了

注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
原文地址:https://www.cnblogs.com/yalphait/p/8646355.html