問題描述
蒜頭君酷愛搭積木,他用積木搭了 n 輛重量為 wi的小車和一艘最大載重量為 w 的小船,他想用這艘小船將 n 輛小車運輸過河。每次小船運載的小車重量不能超過 w。另外,小船在運載小車時,每輛小車會對小船有乙個損壞值si,當多輛小車一起運載時,該趟運載對小船的損壞值為船上所有小車的最大損壞值。
現在蒜頭君想知道,如何用小船運載 n 輛小車,可以使得對小船造成的總損壞值最小。
輸入格式
第一行輸入兩個數 w 和 n(100≤w≤400,1≤n≤16),分別表示小船的最大載重量和小車總數。
接下來輸入 n 行,每行輸入兩個整數si和 wi(1≤si ≤50,10≤wi≤100),分別表示每輛小車對小船的損壞值和每輛小車的重量。
輸出格式
輸出一行,輸出乙個整數,表示用小船運載 nn 輛小車,最小的總損壞值。
樣例輸入
90 4
32 50
15 20
40 50
13 40
樣例輸出
72狀壓dp裡的經典做法,列舉子集。
for(int j=0;j仔細揣摩一下上面的**,這樣列舉子集的效率是很高的。請記住!for(int k=j;k;k=(k-1)&j)
對於這道題很容易想到,對於要求解的任意乙個方案(第i輛搬不搬),可以通過其子集求解,我們列舉其子集代表達成此方案的最後一次運載,取補集就是之前完成的,這樣dp[j]=min。為了提高效率我們可以先預處理出每種情況的花費。
1 #include2 #include3 inline int min(int a,int b)ac**4 inline int max(int a,int b)
5const
int maxw=405,maxn=20,inf=0x3f3f3f3f;6
int w,n,s[maxn],w[maxn],dp[1
<1
<1
<
7int get_w(int
i) 13
return
ans_w;14}
15int get_c(int
i) 21
return
ans_c;22}
23int
main() 34}
35 printf("
%d",dp[(1
<1
]);36
return0;
37 }
計蒜客習題 蒜頭君倒水
推出轉移矩陣 1 xyx1 y begin 1 x y x 1 y end 1 xx y1 y 之後的就很顯然了 倒了幾次就是求轉移矩陣的幾次冪 然後乘上原矩陣 ab begin a b end ab 即可 傳送門注意矩陣乘法不滿足交換律 includeusing namespace std dou...
計蒜客習題 蒜頭君走迷宮
蒜頭君從乙個 n 行 m 列的迷宮的左上角走到右下角,蒜頭君每次只能向下或者向右走一步,蒜頭君想知道他有多少種走法。輸入格式 輸入兩個整數 n 2 n 10 5 m 2 m 10 5 輸出格式 由於方案數太多,輸出最後結果對 1000000007 取模的結果。樣例輸入 2 3 樣例輸出 3 incl...
計蒜客習題 蒜頭君的訓練室
蒜頭君的訓練室有 n 個站點,另外有 m 條單向邊連線這些站點。第 i 條路從 si站到 ei站,有高度為 hi的圍欄,蒜頭君是需要跳躍的。現在蒜頭君們有 t 個任務要完成。第 ii 個任務,蒜頭君要從 ai站到 bi站,蒜頭君想要他們路徑中最高圍欄盡可能小。請你確定這個高度。輸入格式 第一行輸入三...