題目鏈接:HDU - 1421 搬寢室
題意:
n件物體裏面,取2*k件(每次2件),每次疲勞度爲兩件物體質量差的平方,求結束後的最小疲勞度
因爲相鄰的質量差最小,所以可以先排序,每次只用考慮從相鄰的地方取
對於每一個物體,分爲取、不取兩種可能(類似01揹包)
狀態:dp[i][j]:表示從j個裏面選2*i個時,最小的疲勞度
轉移方程:
dp[i][j] = min(dp[i][j-1], dp[i-1][j-2] + (w[i]-w[i-1])*(w[i]-w[i-1]));
核心:
for(i = 1; i<=k; i++) { for(j = i*2; j<=n; j++) { dp[i][j] = min (dp[i][j-1], dp[i-1][j-2] + (w[i]-w[i-1])*(w[i]-w[i-1])); } }
代碼:
#include <stdio.h> #include <iostream> #include <string.h> #include <string> #include <math.h> #include <algorithm> #include <queue> #include <stack> #include <map> #include <vector> #include <time.h> using namespace std; int w[2000+10]; int dp[1000+10][2000+10]; int main() { //freopen("a.txt", "r", stdin); int n, k, i, j; while(~scanf("%d%d", &n, &k)) { for(i = 1; i<=n; i++) { scanf("%d", &w[i]); } sort(w+1, w+n+1); memset(dp, 0, sizeof(dp)); for(i = 1; i<=k; i++) { for(j = i*2; j<=n; j++) { if(j == i*2) dp[i][j] = dp[i-1][j-2] + (w[j]-w[j-1])*(w[j]-w[j-1]); else dp[i][j] = min(dp[i][j-1], dp[i-1][j-2] + (w[j]-w[j-1])*(w[j]-w[j-1])); } } printf("%d\n", dp[k][n]); } return 0; }