题意:乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。(2362是1011的特例,问一堆木棍能否拼成正方形)
思路:dfs+剪枝。其中剪枝具有相当的技巧性,其中一个地方的剪枝没有想到导致tle多次。
几个明显的剪枝点(设ans为最终的答案):
1、ans>=这堆木棍的最大长度
2、ans<=这堆木棍长度的总和
3、ans必可以被这堆木棍长度总和整除
4、对木棍由长到短排序,先考虑长的能有效剪枝
两个不明显但是最重要的剪枝点,缺一不可:
5、如果某次刚刚加入长度为x的木棍而随后搜索失败,则接下来的搜索只需搜比x小得木棍即可(代码中pre变量的作用)。
6、在每次构建新的长度为ans的木棍时,检查新棒的第一根s[i],若在搜索完所有木棍后都无法组合,则说明s[i]无法在当前组合方式下组合,不用往下搜索(因为再怎么搜索s[i]都不会加入到任何一个木棍当中)。代码中if(!from) return 0;这句话的作用。
1011:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define N