1. 程式人生 > >hdoj 1421 搬寢室

hdoj 1421 搬寢室

搬寢室

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 33608 Accepted Submission(s): 11505

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

蜜汁思路:說是一道水題,我也沒寫出來,啊太陽。感覺自己沒dp的腦子。。
先是把輸入進來的重量a[]從小到大排序,
然後用dp[i][j]儲存 在前i個東西中搬j對需要最少的疲勞,
因為是j對,所以i起碼要從2j開始,
當i==2
j時,表示這是從dp[][]中的上一列已經記錄完,當前是新一列的開始,只需要把新包括進來的一對的疲勞加進去就好,即dp[i][j] = dp[i-2][j-1]+(a[i]-a[i-1])(a[i]-a[i-1]),
當i!=2

j時,表示對數沒有變化,要判斷新包括的東西,能不能優化疲勞值,
即dp[i][j] = min(dp[i-1][j],dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1]))。

#include<stdio.h>
#include<algorithm>
#include<string.h>
#define INF 99999999
#define min(a,b) (a)>(b)?(b):(a)
using namespace std;
int main() {
	int n,k;
	int i,j;
	while(scanf
("%d%d",&n,&k)!=EOF) { int a[2050]; for(i=1; i<=n; i++) { scanf("%d",&a[i]); } sort(a+1,a+n+1); int dp[2050][2050]; for(j=1; j<=k; j++) { for(i=2*j; i<=n; i++) { if(i == 2*j) { dp[i][j] = dp[i-2][j-1] + (a[i]-a[i-1])*(a[i]-a[i-1]); } else { dp[i][j] = min(dp[i-1][j],dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1])); } } } printf("%d\n",dp[n][k]); } return 0; }

還要繼續努力