Hdoj 1421.搬寢室 題解
Problem Description
搬寢室是很累的,xhd深有體會.時間追述2006年7月9號,那天xhd迫於無奈要從27號樓搬到3號樓,因為10號要封樓了.看著寢室裏的n件物品,xhd開始發呆,因為n是一個小於2000的整數,實在是太多了,於是xhd決定隨便搬2k件過去就行了.但還是會很累,因為2k也不小是一個不大於n的整數.幸運的是xhd根據多年的搬東西的經驗發現每搬一次的疲勞度是和左右手的物品的重量差的平方成正比(這裏補充一句,xhd每次搬兩件東西,左手一件右手一件).例如xhd左手拿重量為3的物品,右手拿重量為6的物品,則他搬完這次的疲勞度為(6-3)^2 = 9.現在可憐的xhd希望知道搬完這2*k件物品後的最佳狀態是怎樣的(也就是最低的疲勞度),請告訴他吧.
Input
每組輸入數據有兩行,第一行有兩個數n,k(2<=2*k<=n<2000).第二行有n個整數分別表示n件物品的重量(重量是一個小於2^15的正整數).
Output
對應每組輸入數據,輸出數據只有一個表示他的最少的疲勞度,每個一行.
Sample Input
2 1
1 3
Sample Output
4
Author
xhd
Source
ACM暑期集訓隊練習賽(二)
思路
顯然,如果要讓疲勞度最低那麽一定要選擇重量相鄰的,所以要對所有的物品按照重量進行一次排序
用\(f[i][j]\)表示有\(i\)個物品,從中挑\(j\)對物品的最小可能疲勞度,顯然這個狀態只能來自於\(f[i-1][j]\)
狀態轉移方程式為:
\(f[i][j] = min(f[i-1][j], f[i-2][j-1] + (a[i-1]-a[i-2])*(a[i-1]-a[i-2]));\)
\(:且i:2→n;j:1→k 且j<=i\)
代碼
#include<bits/stdc++.h> using namespace std; const int INF = 0xfffffff; int a[2001]; int f[2001][2001]; int main() { int n,k; while(cin>>n>>k) { for(int i=0;i<n;i++) cin >> a[i]; for(int i=0;i<=n;i++) for(int j=0;j<=k;j++) j == 0 ? f[i][j] = 0 :f[i][j] = INF; sort(a,a+n); for(int i=2;i<=n;i++) for(int j=1;j<=k&&j<=i;j++) f[i][j] = min(f[i-1][j], f[i-2][j-1] + (a[i-1]-a[i-2])*(a[i-1]-a[i-2])); cout << f[n][k] << endl; } return 0; }
Hdoj 1421.搬寢室 題解