題目:
又是一道,沒有思想的題,看了題解,我發現我的dp題幾乎都看了題解,我總是想不好狀態轉移方程,汗顏,以後怎麼比賽啊。
先排序,然後說乙個數學問題。
首先,要怎麼搬呢?即每一對要怎麼取?如果有abcd四個數,且a< (a-c)^2+(b-d)^2
(a-b)^2+(c-d)^2 < (a-d)^2+(b-c)^2
即每對物品都應是重量最為接近的物品,也就是說對n件物品排序後,每對物品都應該是連續的。
定義陣列w[i]為搬第i對物品所消耗的疲勞值;陣列dp[n][k]來表示在n件物品中搬k對的最佳狀態,而達到這一狀態的決策可能為:
第n件物品不搬,即在前n - 1件物品中搬k對,那麼疲勞值仍為dp[n - 1][k];
第n件物品要搬,那麼根據上面所證,第n - 1件物品也要同時搬,即在前n - 2件物品中搬k - 1對物品,再搬最後一對物品,那麼疲勞值為dp[n - 2][k - 1] + w[n - 1]。
為使疲勞值最小,因此最佳策略為取兩種決策中的最小值,即應使:
dp[n][k] = min(dp[n - 1][k], dp[n - 2][k - 1] + w[n - 1])應該注意的是要考慮邊界問題,dp[i][j]中:
當2 * j > i時,即要搬的數量超過了物品總量,這是不可能發生的,因此此時令dp[i][j]為無窮大;
當j == 0時,即在一對物品都沒搬時,所需疲勞值應該是0,此時令dp[i][j] = 0。
#include #include#include
#include
#include
#include
#define inf 0x3f3f3f3ftypedef
long
long
ll;using
namespace
std;
int n,k,w[2010],dp[2010][1010
];int
main()
sort(w+1,w+1+n);
for(int i=1;i)
for(int i=0;i<=n;i++)
}for(int i=0;i<=n;i++)
dp[i][
0]=0
; //邊界的處理
for(int i=2;i<=n;i++)
}printf(
"%d\n
",dp[n][k]);
}return0;
}
hdu 1421 搬寢室 dp問題
以前雖然寫過dp問題,但思想上過不去,覺得dp跟遞迴似乎是一樣的,今天寫過這道題後才頓悟 dp與遞迴不是一樣的。狀態方程dp n k min dp n 1 k dp n 2 k 1 w i w j 2 唉,終於發現思想上有所改變了,不過 實現能力不足,在對dp陣列初始化的問題上浪費了n多精力和時間 ...
HDU 1421 搬寢室 線性dp 貪心預處理
problem description 搬寢室是很累的,xhd深有體會.時間追述2006年7月9號,那天xhd迫於無奈要從27號樓搬到3號樓,因為10號要封樓了.看著寢室裡的n件物品,xhd開始發呆,因為n是乙個小於2000的整數,實在是太多了,於是xhd決定隨便搬2 k件過去就行了.但還是會很累,...
HDU 1421 搬寢室 類似揹包DP
思路 把重物從小到大排序,計算出每2個相鄰的重物產生的疲勞度,放在p i 陣列中,表示i與i 1這2個重物產生的疲勞度。dp i j 表示進行到第i個物品 i前面的物品不一定都選了,跟揹包差不多,i表示進行到第i個物品 已經選了j對物品 產生的最小疲勞度。初始化 先把所有值賦值為inf 無窮大 然後...