开始的时候我也认为A,B,C,中只需要对A,B求解即可。。。
但是。。这样的话,最后的结果可能出现A,B,C,(B-C)^2最小或者(A-C)^2最小,而不是我们预想的(A-B)^2最小。
所以这种思路是错的。
我们应该先把每组筷子中最长的那根先给了。。。
所以必须满足条件i*3<=j.....这样就可以肯定,前面的没配对的筷子中有符合条件的长筷。。。
巧妙的思路:::在降序中求解+给出最长筷条件
状态:dp[i][j]表示前i个数中能凑成j对筷子的最小“badness”。
状态转移:dp[i][j] = min(dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]) , dp[i-1][j]);
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 5005
#define N 1010
int k, n, t, a[M], dp[M][N];
int main ()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d", &k, &n);
for(int i = n; i >= 1; i--) scanf("%d",&a[i]);
for(int i = 1; i <= n ;i++)
for(int j = 1; j*3<=i && j <= k+8; j++)
{
dp[i][j] = dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]);
if(j*3!=i) dp[i][j] = min(dp[i][j],dp[i-1][j]);
}
printf("%d\n",dp[n][k+8]);
}
return 0;
}