1 条题解

  • 0
    @ 2026-10-26 10:45:29

    思路与算法

    三个字符分别表示源柱、目的柱、辅助柱,公开样例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

    信息

    ID
    1704
    时间
    1000ms
    内存
    64MiB
    难度
    进阶
    标签
    递交数
    1
    已通过
    1
    上传者