题目中的按升序排列启示了我们DP的顺序,我们先考虑按升序DP,这时会发现决策的时候第i个必定是站在中间的,对答案不产生影响,故无法转移,这样就可以考虑倒着DP,从后往前进行DP。决策的时候需要注意,并不是一个一个的决策,而是两个两个的决策,即每次决策两个最矮的人,这样就容易转移。(所以转移的时候是f[i-2]而不是f[i-3],因为选了i和i-1在1~i-2中剩下的任何一个人都比他们高,不产生影响(这里已经把数组倒序排列))方程容易写出。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int f[10000][2000],a[10000];
int main()
{
int m,n;
memset(f,63,sizeof(f));
f[0][0]=0;
cin>>m>>n;
for(int i=1;i<=n;i++)
{
int x;f[i][0]=0;
cin>>x;
a[n-i+1]=x;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=min(m,i/3);j++)
f[i][j]=min(f[i-1][j],f[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]));
cout<<f[n][m];
while(1);
return 0;
}