2018 10 2 菌落合併

2022-05-02 04:09:09 字數 2613 閱讀 9942

【題目描述】

小 $m$ 培養了 $n$ 個菌落。其中每個菌落有質量和顏色兩種屬性,顏色只可能為紫色或紅色。小 $m$ 想把所有的菌落合併成乙個菌落。因為合併的過程非常費勁,小 $m$ 每天只能進行一次合併,整個過程需要進行 $n − 1$ 天。一次合併會將兩個菌落變成乙個菌落。如果原來兩個菌落的顏色相同,兩個菌落會進行融合,新的菌落質量為原來兩個菌落質量之和,顏色不變;如果原來兩個菌落的顏色不同,兩個菌落會進行戰鬥,新的菌落質量為原來兩個菌落質量之差,顏色為質量較大的那個菌落。需要特殊說明的是,中間過程中如果產生了質量為 $0$ 的菌落,這個菌落也需要參與後續合併而不能直接捨棄;可以證明將質量為 $0$ 的菌落視為紫色或紅色都不影響後續的計算。

每天的合併結束後,小 $m$ 都需要餵養當前的每個菌落。對於乙個質量為 $w$ 的菌落,小 m 需要花費 $w^2$ 單位的能量對它進行一天的餵養。

小 $m$ 希望你幫他求出菌落的最佳合併順序,使得餵養所消耗的總能量最少。你只需要輸出所需要的最小能量即可。

【輸入格式】

從檔案 germ.in 中讀入資料。

輸入的第一行包含乙個正整數 $t$,表示資料的組數。對於所有的測試點,保證$ t = 10$。

對於每組資料,第一行包含乙個正整數 $n$,表示最初菌落的個數。

接下來 $n$ 行,每行包含乙個正整數和乙個字串,表示這個菌落的質量和顏色。若字串為 $743481$,表示這個菌落是紫色;若字串為 $8b0012$,表示這個菌落是紅色。保證不會出現其他的字串,保證給出的正整數不超過 $10^6$ 。

【輸出格式】

輸出到檔案 germ.out 中。

對於每組資料,輸出一行乙個整數,表示消耗的最少總能量。注意這個值可能很大,請注意選用合適的資料型別來儲存它。

【樣例輸入】104

3 743481

20 743481

7 8b0012

18 743481

310 8b0012

13 743481

13 8b0012

514 743481

16 8b0012

2 8b0012

9 8b0012

8 8b0012

411 8b0012

15 8b0012

4 8b0012

8 8b0012

211 8b0012

6 8b0012

48 8b0012

16 8b0012

16 8b0012

3 8b0012

220 743481

17 743481

36 8b0012

20 743481

13 8b0012

419 8b0012

15 743481

4 8b0012

1 743481

211 8b0012

14 8b0012

【樣例輸出】

2238

200980

2688

2893467

1369

86107

625【樣例解釋】

對於樣例中的第一組資料,最優的合併方案如下:

1. 合併紫色的 $20$ 和紅色的 $7$,得到紫色的 $13$;餵養的能量花費為 $3^2 +13^2 +18^2 = 502$。

2. 合併紫色的 $13$ 和紫色的 $3$,得到紫色的 $16$;餵養的能量花費為 $16^2 +18^2 = 580$。

3. 合併紫色的 $16$ 和紫色的 $18$,得到紫色的 $34¥;餵養的能量花費為 ¥34^2 = 1156$。

可以證明沒有更優的方案。

【子任務】

$n<=10$。

對於全是同一種顏色的情況,不能從小到大兩兩合併,這樣得出來的解並不是最優的,同色的1~10就是個反例。

可以當做乙個模擬退火題:

模擬退火題的典例——哈密頓迴路題有個較優演算法:將初始退火序列設為圖的最小生成樹的遍歷。

也可以當做乙個貪心暴力折中題:

把這題的暴力和貪心對比一下(當然貪心的結果會大一點點),會發現貪心出現的少量錯誤答案只比暴力的正確答案多一點點,然後輸出一下路徑,發現貪心的路徑與暴力的路徑很相似。因此把每一步的$n^2$列舉的所有情況所導致的結果從小到大排序,然後跑前幾種即可(mangod跑了5個就a了)。

std:

f(i,s)表示合併i次後時,經過的點的集合是s。

這個集合s怎麼表示?

我們都知道,s是把集合壓成乙個數,代表一種情況。

然而這裡並不能只存個表示01二進位制序列的數,表示乙個數選或不選,因為乙個數在被合併入不同的菌落時,是有不同的後效性的(後效性就是說前面的決策對後面所有答案都有影響),因此有多種不同的合併情況需要被統計。

也就是說,我們需要記錄每個數被合併到了哪個菌落裡。這就需要並查集的思想了。

我們讓每個初始菌落存乙個數,表示這個菌落被合併若干次後,該菌落中編號最小的初始菌落的編號。那麼存的這個數相同的初始菌落就都已經被合併到乙個菌落裡了。

容易發現,每個初始菌落存的數都不會超過自己的編號。

那麼$n$個初始菌落的編號總種數就是$n!$,一看$n=10$,總種數大約$100w$。這就可以狀態壓縮了。

轉移方程:

複雜度:$o(n!

計算思維綜合訓練 D 2018102

個人新增了注釋,答案由學校課程組給出,不是原創回答 include using namespace std int daynum 13 bool checkyear int x 判斷給出的年份x是否為閏年 void nxt int a,int b,int c 移動到下乙個日期 if b 12 if ...

單鏈表的合併(交叉合併,公升序合併)

單鏈表的合併情況有如下幾種 1 length l1 length l2 2 length l1 length l2 3 length l1 交叉合併的重點在交叉,不保證合併後的資料是有序的 公升序單鏈表合併的重點在公升序,可以保證合併後的資料是公升序的,但是前提是輸入的鍊錶是公升序的 include...

Pandas合併之Concat合併

pd.concat objs,axis 0,join outer join axes none,ignore index false,keys none,levels none,names none,verify integrity false objs series或者dataframe物件構成的...