1 条题解
-
0
思路与算法
三个字符分别表示源柱、目的柱、辅助柱,公开样例2 a b c最终把塔从a移到b。递归moveTower(n,from,to,spare):先把上面n-1个盘从from移到spare,再输出把第n号盘从from移到to,最后把n-1个盘从spare移到to。n=0时不做操作。
输出严格为源柱->盘号->目的柱,每次一行;柱名取输入字符,不写死a、b、c。这样既满足移动约束,也按指定顺序输出完整过程。
正确性说明
对盘数归纳。0个盘无需移动,结论成立。假设少于n个盘的递归都能合法地把整塔移到目标柱。先递归移动n-1个小盘到辅助柱后,第n个盘成为源柱顶部,目的柱没有更小盘,可以合法移过去。再根据归纳假设把辅助柱的小塔放到该大盘上,仍不出现大盘压小盘,最终全部n个盘位于目的柱。
任何合法方案在移动最大盘到目的柱前,都必须把上方n-1个盘移到辅助柱,之后又必须把它们移回目的柱;因此至少需要2T(n-1)+1步。本算法恰好这么多步,给出最少且合法的完整移动序列。
复杂度
调用次数和移动次数满足T(n)=2T(n-1)+1,分别为O(2^n)和2^n-1,输出为主的总时间O(2^n),递归栈深度O(n),额外空间O(n)。程序只存盘数和三个柱名,初始化O(1),不缓存全部移动。盘数小于20,最大19盘524287条记录,实际验证该完整输出及原1秒/64MiB资源。
易错点
目的柱是第二个输入字符,第三个才是辅助柱,以公开样例核准。递归调用要同时交换正确的源、目的、辅助角色。盘号从小到大为1到n。每行箭头格式一致,不输出额外说明或总步数。最大输出略超过默认QA工具4MiB,此批仅把隔离单次命令stdout上限设为8MiB,不改服务全局配置;原生判题仍按题目原资源验证。
参考代码(C++11)
#include <iostream> using namespace std; void moveTower(int n, char from, char to, char spare) { if (n == 0) return; moveTower(n - 1, from, spare, to); cout << from << "->" << n << "->" << to << '\n'; moveTower(n - 1, spare, to, from); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; char a, b, c; cin >> n >> a >> b >> c; moveTower(n, a, b, c); }
- 1