递归裁剪纸张作业求助:编写基于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); } } }
代码解释
- 参数处理:先检查命令行参数是否合法,确保输入的是一个非负整数;
- 画布设置:把A0的宽设为√2,高设为1,严格符合ISO的宽高比;
- 递归函数:
- 基线条件:当
remainingCuts为0时,停止递归,不需要再画裁剪线; - 竖切逻辑:计算当前纸张的x中点,画竖直线,然后递归处理左右两个子纸张,剩余裁剪次数减1,下次改为横切;
- 横切逻辑:计算当前纸张的y中点,画水平线,然后递归处理上下两个子纸张,剩余裁剪次数减1,下次改为竖切。
- 基线条件:当
这样运行代码时,比如输入java PaperCutter 3,就会看到A0被裁剪成8份,完全符合要求。
内容的提问来源于stack exchange,提问作者Sameer Acharya
相关产品推荐
相关产品推荐

