You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归裁剪纸张作业求助:编写基于StdDraw的A0纸裁剪可视化程序

嘿,这个递归裁剪ISO纸张的问题我之前也碰到过,挺适合用递归来解决的!让我一步步给你理清楚思路,再给你个可运行的代码示例。

思路分析

首先,我们得明确裁剪规则:

  • A0纸宽高比是√2:1,面积1㎡;
  • 第1次裁剪(n=1):沿竖线把A0切成2个A1;
  • 第2次裁剪(n=2):对每个A1沿横线切成2个A2,总共4份;
  • 以此类推,n次裁剪后得到2^n份,每次裁剪方向交替(竖→横→竖→横...)。

递归的核心逻辑很清晰:把当前的纸张区域拆分成两个子区域,分别递归处理剩下的n-1次裁剪,直到n=0时停止(不需要再裁剪)。

代码实现(Java + StdDraw)

这里用Java编写,因为StdDraw通常是Java教学中用的库。代码里已经处理了命令行参数、画布设置,还有递归绘制裁剪线的逻辑:

import edu.princeton.cs.algs4.StdDraw;

public class PaperCutter {
    public static void main(String[] args) {
        // 处理命令行参数
        if (args.length != 1) {
            System.out.println("请输入一个非负整数参数n,用法:java PaperCutter <n>");
            return;
        }
        int n;
        try {
            n = Integer.parseInt(args[0]);
            if (n < 0) {
                System.out.println("n必须是非负整数哦");
                return;
            }
        } catch (NumberFormatException e) {
            System.out.println("参数必须是整数!");
            return;
        }

        // 设置画布坐标,保证A0宽高比为√2:1
        double a0Width = Math.sqrt(2);
        double a0Height = 1.0;
        StdDraw.setXscale(0, a0Width);
        StdDraw.setYscale(0, a0Height);

        // 先画出A0的边框,方便观察
        StdDraw.rectangle(a0Width / 2, a0Height / 2, a0Width / 2, a0Height / 2);

        // 启动递归绘制裁剪线,第一次是竖切
        drawCuts(0, 0, a0Width, a0Height, n, true);
    }

    /**
     * 递归绘制裁剪线
     * @param x1 当前纸张左下角x坐标
     * @param y1 当前纸张左下角y坐标
     * @param x2 当前纸张右上角x坐标
     * @param y2 当前纸张右上角y坐标
     * @param remainingCuts 剩余需要裁剪的次数
     * @param isVertical 当前是否要竖切
     */
    private static void drawCuts(double x1, double y1, double x2, double y2, int remainingCuts, boolean isVertical) {
        // 基线条件:没有剩余裁剪次数,直接返回
        if (remainingCuts == 0) {
            return;
        }

        if (isVertical) {
            // 竖切:在x中点画竖直线
            double midX = (x1 + x2) / 2;
            StdDraw.line(midX, y1, midX, y2);
            // 递归处理左右两个子区域,剩余次数减1,下一次改为横切
            drawCuts(x1, y1, midX, y2, remainingCuts - 1, false);
            drawCuts(midX, y1, x2, y2, remainingCuts - 1, false);
        } else {
            // 横切:在y中点画水平线
            double midY = (y1 + y2) / 2;
            StdDraw.line(x1, midY, x2, midY);
            // 递归处理上下两个子区域,剩余次数减1,下一次改为竖切
            drawCuts(x1, y1, x2, midY, remainingCuts - 1, true);
            drawCuts(x1, midY, x2, y2, remainingCuts - 1, true);
        }
    }
}
代码解释
  1. 参数处理:先检查命令行参数是否合法,确保输入的是一个非负整数;
  2. 画布设置:把A0的宽设为√2,高设为1,严格符合ISO的宽高比;
  3. 递归函数:
    • 基线条件:当remainingCuts为0时,停止递归,不需要再画裁剪线;
    • 竖切逻辑:计算当前纸张的x中点,画竖直线,然后递归处理左右两个子纸张,剩余裁剪次数减1,下次改为横切;
    • 横切逻辑:计算当前纸张的y中点,画水平线,然后递归处理上下两个子纸张,剩余裁剪次数减1,下次改为竖切。

这样运行代码时,比如输入java PaperCutter 3,就会看到A0被裁剪成8份,完全符合要求。

内容的提问来源于stack exchange,提问作者Sameer Acharya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 07:48:14