暴搜 + 毒瘤剪枝。
说说这道花了我三四天才调处来的毒瘤暴搜。
事实证明,该借鉴题解时就要借鉴题解。
不过做完这题之后确实对深搜、优化、剪枝有了更深刻的理解。
题意
给 n n n 个小木棒的长度,求他们最多能拼成的长度相同木棍的长度。
下文为了区分,把短的(用来拼的)叫做(小)木棒,长的(被拼接成的)叫做木棍。
思路
试试我新的思路写法。
1
二分?dp?贪心?似乎都不是。
最后认命地发现它就是一道朴素的暴搜,但却有毒瘤的剪枝。
所以暴搜的大致解法就是:
很明显,我们要先枚举若干根木棍的长度,再拿他来拼接,dfs 判断是否能拼接成功。
每次 dfs 就一根根木棒拼接,看最后是否能拼接成 n / l e n n/len n/len 根的木棍。
注意输入的时候忽略掉那些长度比 50 要大的木棒。
2
先说有点东西的主函数。
首先,在输入了木棒的长度之后要对他们从大到小排序。
易知,相比一根短木棒,长木棒拼接起来会更有限制性,即更短的木棒可以和其他有更多种拼接可能。
也可以理解为短木棒比长木棒更加灵活。
所以,我们在拼接时,就要优先选择长木棒,其次才是短木棒(优化 1)。
其次,可以发现,木棍的长度是有限制的:
-
l e n ∣ s u m len | sum len∣sum(其中 sum 是木棒总长度,len 是当前枚举木棍长度)。
原因很简单,每根木棍的长度相等(题目条件)。
-
l e n ≤ s u m 2 len \le \dfrac{sum}{2} len≤2sum 或 l e n ← s u m len \gets sum len←sum。
因为除了拼接成一根长的木棍之外,木棒至少拼接成两根以上的木棍。
综上所述,
我们只需要枚举 len 从 最长木棒长度(最长木棒不能切割,所以木棒必须包含它)
到 s u m 2 \dfrac{sum}{2} 2sum,每次如果成功拼接,直接输出结束程序,否则最后跳出循环输出 sum(优化 2)。
3
然后说说出场率最高的 dfs。
每次传递三个变量——k、lst、rst,分别表示当前拼接的木棍编号、上一根被拼接的木棒编号,以及拼接完当前木棍还需要的木棒长度。
主要分成 3 个部分。
1
如果拼接成功,
即 k =