题意。。。
首先从小到大排个序,并且分析之后可得, 如果要去第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