解析:
f[i][j]:表示第i天,选j道题
怎么才能使得最小呢,我们一定要先排个序
对于第一天来说,我可以选择的题数1~n,所以先预处理第一天选j题的情况。
到这里已经两重循环了,但是状态转移方程还没出来,我们要寻找分界点。
分界点
假设f[2][j]:表示第2天,选了j道题。那么第一天选的题数可以表示f[1][1~j-1]
所以再写一个循环,枚举前一天选的题数
状态方程:f[i][j]=min(f[i][j],f[i-1][k]+abs(a[j]-a[k+1])*abs(a[j]-a[k+1]);
为什么是k+1,因为 f[i-1][k]表示第i-1天,选了k道题。那么我们自己选的时候一定从k+1开始选
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[10005];
ll f[1000][1000]; //表示第i天,选j道题
int t,n,m;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+1+n);
memset(f,0,sizeof f);
//预处理一下
for(int i=1;i<=n;i++) f[1][i]=abs(a[i]-a[1])*abs(a[i]-a[1]);
for(int i=2;i<=m;i++)//天数
{
for(int j=1;j<=n;j++)//题数
{
f[i][j]=1e18;//初始化
for(int k=1;k<j;k++)//枚举第i-1天选的题数
{
//f[i-1][k]表示第i-1天,选了k道题,那么就是k+1和j比较
f[i][j]=min(f[i][j],f[i-1][k]+abs(a[j]-a[k+1])*abs(a[j]-a[k+1]));
}
}
}
cout<<f[m][n]<<endl;
}
}