2019 GDUT Winter Training I (dfs/bfs/二分/三分/尺取) H - dfs
专题传送门
poj传送门
题目大意:
大概就是有个人闲着无聊,把不知道多少根等长的木棍砍成短木棍,但忘记了初始时有多少木棍以及木棍的初始长度,现在给你砍完后短木棍的长度,问你初始木棍的可能最小长度。
题目分析:
现在我们应该容易从题目看出下面的隐藏条件 (剪枝)。剪不够就TLE到要哭
1.长木棍的长度大于等于最长的短木棍。
2.短木棍长度之和一定可以整除长木棍的长度。
3.将短木棍从长到短排更容易找到答案,因为在组合的时候长棍子不灵活。
4.如果某个短棍子在一次组合中不满足要求,那么就不需要考虑和它相等长度的棍子了。
5.如果当前最长的一支可用小棒L0恰能填满当前正在组合的一支原棒,则如果此次尝试失败,在当前状态下不再做其它尝试,返回上一层递归。因为若当前状态成功,则当前原棒的剩余长度必定能由另几支更短的小棒L1、L2……Ln组合成,且L0必定出现在之后组合的某支原棒之中,则可以将其中的L0替换为L1、L2……Ln,而将L0移加当前原棒中,则两种状态等价,因此同样必定失败。因此,在stick[i]==len时,若搜索失败,则同样停止当前状态的其它搜索。
6.在一次组合的第一步,如果是组合的第一步,而且没找到合适的组合,那么就可以结束尝试了,因为该棍子迟早要用于一种组合之中的。
这题我们可以用dfs不断尝试原始木棍的长度,直到得到答案。
这里我dfs传递的参数是剩余木棍的总长度,以及当前在组合的棍子的长度,当剩余木棍总长度和当前组合的棍子的长度为0时才能返回true,即组合成功。
还要注意回溯,如果组合失败就回溯,即取消之前棍子的标记。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int