正如提示中所说的,先想明白怎样求没有第三支筷子限制时的解答方式,仍然是递推的思路,利用已经求出的在某支筷子前匹配出多少双筷子的最小代价计算下一支筷子的结果。然后考虑从长的筷子往短的筷子计算,这实在是意外的技巧。
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <assert.h>
#include <algorithm>
#include <math.h>
#include <ctime>
#include <functional>
#include <string.h>
#include <stdio.h>
#include <numeric>
#include <float.h>
using namespace std;
const int K = 1500;
const int N = 5100;
const int INF = 12000000;
int dp[K][N];
int bad[N];
int main() {
int TC = 0; cin >> TC;
for (int tc = 0; tc < TC; tc++) {
int k, n; cin >> k >> n; k += 8;
vector<int> len(n);
for (int i = 0; i < n; i++) {
cin >> len[i];
}
for (int i = n - 2; i >= 0; i--) {
bad[i] = (len[i] - len[i + 1]) * (len[i] - len[i + 1]);
}
memset(dp, 0, sizeof(dp));
for (int i = 1; i < K; i++) {
for (int j = 0; j < N; j++) {
dp[i][j] = INF;
}
}
for (int i = n - 2; i >= 0; i--) {
for (int j = 1; j <= k; j++) {
if (n - i < j * 3) break;
dp[j][i] = min(dp[j][i+1], dp[j-1][i+2] + bad[i]);
}
}
cout << dp[k][0] << endl;
}
return 0;
}