dp[i][j] = min(dp[i - 2][j - 1] + (v[i] - v[i - 1]) * (v[i] - v[i - 1]), dp[i - 1][j]);
事先对物品重量v进行排序,则只有相邻两件物品之差最小。
对于dp[i][j]其中i表示物品n,j表示搬运次数k,结果为dp[n][k]。
策略有两种,一种为选取当前第i件物品,那么得到公式dp[i - 2][j - 1] + (v[i] - v[i - 1]),一种为不选当前i物品,则dp[i -1][j]。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX_NUM = 0x7fffffff;
int dp[2005][1005];
int main(){
int n, k, v[2005];
while (~scanf("%d%d", &n, &k)){
memset(v, 0, sizeof(v));
for (int i = 1; i <= n; i++)
scanf("%d", &v[i]);
sort(v + 1, v + n + 1);
for (int i = 0; i <= n; i++)
for (int j = 0; j <= k; j++)
dp[i][j] = MAX_NUM;
for (int i = 0; i <= n; i++)
dp[i][0] = 0;
for (int i = 2; i <= n; i++)
for (int j = 1; j * 2 <= i; j++)
dp[i][j] = min(dp[i - 2][j - 1] + (v[i] - v[i - 1]) * (v[i] - v[i - 1]), dp[i - 1][j]);
printf("%d\n", dp[n][k]);
}
return 0;
}