题意。。。
首先从小到大排个序,并且分析之后可得, 如果要去第i个的话,则第i-1个物品也要取(因为是排过序的与i相差最小的就是i-1或者是i+1, 但是i+1与i也可以看做i和i-1, 所以如果要去第i个的话,则第i-1个物品也要取)。
分析:设dp[i][j]表示有i个物品,拿j对。则第i个物品对dp[i][j]有两种情况:
一:如果要不取第i个物品, 则此时的dp[i][j] = dp[i-1][j](仔细考虑一下)
二:如果要取第i个物品, 则此时有dp[i][j] = dp[i-2][j-1]+pow2(s[i]-s[i-1])(因为如果要去第i个的话,则第i-1个物品也要取,所以就是i-2,又因为又取了一对,所以是j-1);
注1:又因为是要找最小的疲劳值,所以取上面两种情况的最小值。
注2:初始化的时候dp[i][0] = 0,其他的都初始化为较大的数
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define M 2050
#define INF 0x7f7f7f7f
using namespace std;
int s[M];
int dp[M][M];
int pow2(int x){
return x*x;
}
void solve(int n, int m){
int i, j;
for(i = 1; i <= n; i ++){
for(j = 1; j <= n/2; j ++){
dp[i][j] = INF;
}
dp[i][0] = 0;
}
for(i = 2; i <= n; i ++){
for(j = 1; j <= i/2; j ++){
dp[i][j] = min(dp[i-1][j], dp[i-2][j-1]+pow2(s[i]-s[i-1]));
}
}
printf("%d\n", dp[n][m]);
}
int main(){
int n, m, i;
while(scanf("%d%d", &n, &m) == 2){
for(i = 1; i <= n; i ++){
scanf("%d", &s[i]);
}
sort(s+1, s+n+1);
solve(n, m);
}
return 0;
}原文地址:http://blog.csdn.net/shengweisong/article/details/38864901