算法解题入门:先取例,再找规律
陌生题目不一定需要马上找到一个高级算法。很多时候,先把问题缩小到能手算的规模,就能看见下一步。
从一件能数清的小事开始
问题:笼子里只有鸡和兔,共有 4 个头、10 条腿。鸡有 2 条腿,兔有 4 条腿。各有多少只?
先明确模型:每只动物恰好贡献一个头,鸡和兔的数量都是非负整数。
先枚举兔的数量。若有 x 只兔,鸡就有 4 − x 只。于是腿的总数是 4x + 2(4 − x)。不需要把鸡、兔的数量分别做两层枚举,因为“总共 4 个头”已经把两个变量联系起来了。
| 兔的数量 x | 鸡的数量 4 − x | 腿的总数 |
|---|---|---|
| 0 | 4 | 8 |
| 1 | 3 | 10 |
| 2 | 2 | 12 |
| 3 | 1 | 14 |
| 4 | 0 | 16 |
表格告诉我们,这个例子的答案是 3 只鸡、1 只兔。更重要的观察是:每把一只鸡换成兔,头数不变,腿数增加 2。
把观察变成一个可以检验的猜想
设头数为 H,腿数为 L。如果所有动物都是鸡,腿数应为 2H。每多一只兔,就多出 2 条腿,所以兔的数量可能是 (L − 2H) ÷ 2。
先不要把这个式子直接当成万能答案。试试 H = 4、L = 9:算出的兔数不是整数,说明这个输入没有符合模型的解。再试 H = 4、L = 18:兔数超过头数,同样不合法。
为什么公式成立,还需要什么条件?
若鸡有 c 只、兔有 r 只,那么 c + r = H,2c + 4r = L。把第一式乘以 2,再从第二式中减去,得到 2r = L − 2H,因此 r = (L − 2H) / 2,c = H − r。
要让答案合法,至少需要:H、L 都是非负整数,2H ≤ L ≤ 4H,并且 L − 2H 是偶数。在这些条件下,r、c 都是非负整数,并且代回两个等式就能同时满足头数和腿数要求。
这里完成了两件事:说明为什么不会漏掉合法答案,以及说明计算出的答案确实合法。只用一组样例检验,无法代替这两部分论证。
枚举不是“低级方法”
枚举所有可能,再逐个检查,是很多算法的起点。关键要说清楚三件事:枚举的对象是什么,取值范围是多少,什么条件算合法。在这个问题中,枚举兔数 x = 0 到 H,每一个可能的鸡兔组合都会对应其中一个 x,因此不会遗漏。
当 H 很小时,枚举已经足够。当 H 很大时,公式可以把检查次数降下来。先有正确而清楚的直接方法,再根据数据范围决定是否需要优化。
遇到新题,可以沿着这条线思考
- 进入题目:分清已知条件、目标和限制。
- 取小例子:尝试最小情况、零值、极端情况或有规律的数据。
- 找结构:观察哪些量变化、哪些量保持不变。
- 提猜想:把发现写成明确、可被反例推翻的陈述。
- 给论证:说明方法为何不漏、不重、不接受非法情况。
- 回看迁移:条件改变后,哪些步骤仍然适用?
例如,如果第三种动物也能出现,就不能只用鸡兔的两个未知量来建模。真正值得记住的是“利用已知关系减少独立变量”,而不只是一个公式。