开始的时候我也认为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; }