1. 程式人生 > 其它 >Google Code Jam 2022 Round1A

Google Code Jam 2022 Round1A

Double or One Thing

做法1

假設當前字元比下一個字元小,那麼複製一遍肯定更優。

假設當前字元比下一個字元大,那麼複製一遍肯定更優。

假設當前字元和下一個字元相等,那麼就看下一個不等的字元的大小,更大就這一串全複製,不然就全不復制。

做法2

從後面開始貪心,每次看是否複製,貪心的選小的。

Equal Sum

比賽的時候想到了利用二進位制來構造任何數,但是就是差一步。

首先,把\(\{2^i | 0\le i \le 29\}\)共30個數加入\(A\),剩下70個數隨意。

然後再輸入進來100個數。

考慮先將後170個數分成兩個集合\(A\)\(B\),記\(S(x)\)表示集合\(x\)

中元素之和。依次考慮每一個數,每次將數加入較小的那個集合,易得這樣的話\(S(A)\)\(S(B)\)的差值是小於\(10^9\)的。

後面考慮用2的冪次來消除差值。現在需要劃分的200個數都確定了,他們的和能確定,最後兩個集合相等,那麼其中一個集合的和\(S\)也確定了。

現在考慮把較小的那個集合,假設它的元素和為\(S^{\prime}\)吧,用2的冪次補到\(S\)。易得\(S\)的取值介於\(S(A)\)\(S(B)\)之間,所以\(d = S - S^{\prime}\)的值會小於\(10^9。然後根據\)d$的二進位制可以輕易做到。

Weightlifting

比賽的時候沒想出來,寫了一小時爆搜都沒恰到部分分。

對於一個區間內的訓練(exercise),可以先將區間內共有的負重(weights)加入棧中,對於該區間而言加入的順序不影響結果,等這個區間都處理完了之後,再依次出棧。

對於一個區間,可以將其拆分為兩個部分,先做左區間,在做右區間,對於每一個區間,都利用上述觀察,這樣問題就可以通過一個遞迴的過程解決,然後結合記憶話搜尋或者說區間DP,就可以解覺問題,複雜度大概在立方級別。

具體而言就是,記\(c(l, r)\)為區間\([l,r]\)中所有訓練共有的負重數量,\(dp(1, n)\)為區間\([l, r]\)除了共有的負重之外還需要的代價。那麼最後的答案就是\(dp(1, E) + 2 c(1, E)\)

,然後有

\[dp(l, r) = \left\{ \begin{aligned} &0 & l = r \\ &\min_{l \le i \le r - 1}(dp(l, i) + dp(i + 1, r) + 2(c(l, i) - c(l, r)) + 2 (c(i + 1, r) - c(l, r))) & \text{otherwise}\\ \end{aligned} \right. \]