背景
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
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\n",f[1][m]); 25 return 0; 26 }
状态转移方程:f[x][y]记录最高的那x人里分y组时最小残疾值
f[x][y]=min{f[x+1][y],f[x+2][y-1]}
倒序处理是为了保证下一个人一定是一组中站在两边的(比较矮)
防止出现凑齐了俩人却没有高个子补上的尴尬情况
正序的话就变成加的那个人肯定是高个了 组的情况就不那么明确了