摘要
本文描述了一个经典的"蠕虫爬井"模拟问题。蠕虫从井底(高度为0)开始,每分钟上爬 U 寸,随后必须休息一分钟,期间下滑 D 寸(D < U)。题目要求计算蠕虫头部到达井口(深度 N 寸)所需的总时间(分钟),并规定不足一分钟按一分钟计,且一旦在上爬过程中到达井口即视为完成。
输入为三个正整数 N、U、D(N ≤ 100),输出为总时间。文中提供了完整的 C 语言实现代码,采用直接模拟的算法,并附有详细的行内注释。算法核心是循环模拟上爬与下滑过程,时间复杂度为 O(N/(U-D)),同时总结了边界条件、时间计数等关键注意事项。
题目描述
一条蠕虫长1寸,在一口深为 N 寸的井的底部。已知蠕虫每1分钟可以向上爬 U 寸,但必须休息1分钟才能接着往上爬。在休息的过程中,蠕虫又下滑了 D 寸。就这样,上爬和下滑重复进行。请问,蠕虫需要多长时间才能爬出井?
这里要求不足1分钟按1分钟计,并且假定只要在某次上爬过程中蠕虫的头部到达了井的顶部,那么蠕虫就完成任务了。初始时,蠕虫是趴在井底的(即高度为0)。
输入格式:
输入在一行中顺序给出3 个正整数 N、U、D,其中D<U,N不超过100。
输出格式:
在一行中输出蠕虫爬出井的时间,以分钟为单位。
输入样例:
12 3 1
输出样例:
11
代码部分实现
c
#include <stdio.h>
int main(void)
{
// 变量定义
int N, U, D, time = 0, height = 0; // N: 井深,U: 每分钟上爬距离,D: 每分钟下滑距离,time: 累计时间,height: 当前高度
scanf("%d %d %d", &N, &U, &D); // 读取输入的三个正整数 N, U, D
// 模拟蠕虫爬井过程
while (1) {
time++; // 上爬花费1分钟
height += U; // 上爬 U 寸
if (height >= N) { // 判断是否到达或超过井口
break; // 到达井口,跳出循环
}
time++; // 下滑前休息1分钟(计入总时间)
height -= D; // 下滑 D 寸
}
printf("%d\n", time); // 输出总时间
return 0;
}
算法流程图
下面是蠕虫爬井算法的流程图,展示了程序的执行逻辑:
#mermaid-svg-h8BKQMNhEczvdPLn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-h8BKQMNhEczvdPLn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-h8BKQMNhEczvdPLn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-h8BKQMNhEczvdPLn .error-icon{fill:#552222;}#mermaid-svg-h8BKQMNhEczvdPLn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-h8BKQMNhEczvdPLn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-h8BKQMNhEczvdPLn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-h8BKQMNhEczvdPLn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-h8BKQMNhEczvdPLn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-h8BKQMNhEczvdPLn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-h8BKQMNhEczvdPLn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-h8BKQMNhEczvdPLn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-h8BKQMNhEczvdPLn .marker.cross{stroke:#333333;}#mermaid-svg-h8BKQMNhEczvdPLn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-h8BKQMNhEczvdPLn p{margin:0;}#mermaid-svg-h8BKQMNhEczvdPLn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-h8BKQMNhEczvdPLn .cluster-label text{fill:#333;}#mermaid-svg-h8BKQMNhEczvdPLn .cluster-label span{color:#333;}#mermaid-svg-h8BKQMNhEczvdPLn .cluster-label span p{background-color:transparent;}#mermaid-svg-h8BKQMNhEczvdPLn .label text,#mermaid-svg-h8BKQMNhEczvdPLn span{fill:#333;color:#333;}#mermaid-svg-h8BKQMNhEczvdPLn .node rect,#mermaid-svg-h8BKQMNhEczvdPLn .node circle,#mermaid-svg-h8BKQMNhEczvdPLn .node ellipse,#mermaid-svg-h8BKQMNhEczvdPLn .node polygon,#mermaid-svg-h8BKQMNhEczvdPLn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-h8BKQMNhEczvdPLn .rough-node .label text,#mermaid-svg-h8BKQMNhEczvdPLn .node .label text,#mermaid-svg-h8BKQMNhEczvdPLn .image-shape .label,#mermaid-svg-h8BKQMNhEczvdPLn .icon-shape .label{text-anchor:middle;}#mermaid-svg-h8BKQMNhEczvdPLn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-h8BKQMNhEczvdPLn .rough-node .label,#mermaid-svg-h8BKQMNhEczvdPLn .node .label,#mermaid-svg-h8BKQMNhEczvdPLn .image-shape .label,#mermaid-svg-h8BKQMNhEczvdPLn .icon-shape .label{text-align:center;}#mermaid-svg-h8BKQMNhEczvdPLn .node.clickable{cursor:pointer;}#mermaid-svg-h8BKQMNhEczvdPLn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-h8BKQMNhEczvdPLn .arrowheadPath{fill:#333333;}#mermaid-svg-h8BKQMNhEczvdPLn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-h8BKQMNhEczvdPLn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-h8BKQMNhEczvdPLn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-h8BKQMNhEczvdPLn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-h8BKQMNhEczvdPLn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-h8BKQMNhEczvdPLn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-h8BKQMNhEczvdPLn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-h8BKQMNhEczvdPLn .cluster text{fill:#333;}#mermaid-svg-h8BKQMNhEczvdPLn .cluster span{color:#333;}#mermaid-svg-h8BKQMNhEczvdPLn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-h8BKQMNhEczvdPLn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-h8BKQMNhEczvdPLn rect.text{fill:none;stroke-width:0;}#mermaid-svg-h8BKQMNhEczvdPLn .icon-shape,#mermaid-svg-h8BKQMNhEczvdPLn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-h8BKQMNhEczvdPLn .icon-shape p,#mermaid-svg-h8BKQMNhEczvdPLn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-h8BKQMNhEczvdPLn .icon-shape .label rect,#mermaid-svg-h8BKQMNhEczvdPLn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-h8BKQMNhEczvdPLn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-h8BKQMNhEczvdPLn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-h8BKQMNhEczvdPLn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
开始
初始化
time = 0, height = 0
读取输入 N, U, D
循环开始
上爬阶段
time++
height += U
height >= N?
输出 time
程序结束
休息/下滑阶段
time++
height -= D
结束
该流程图清晰地展示了:
- 初始化阶段:设置时间和高度为0
- 输入读取:获取井深N、上爬距离U、下滑距离D
- 循环模拟 :
- 上爬阶段:时间增加1分钟,高度增加U寸
- 判断是否到达井口:如果高度≥井深,则跳出循环输出结果
- 下滑阶段:时间再增加1分钟,高度减少D寸
- 循环继续:返回循环开始,继续下一轮上爬
算法总结
核心思想
本算法采用模拟 方法,逐分钟模拟蠕虫的上爬与下滑过程。每次循环代表一个"上爬+下滑"的完整周期(实际为两分钟),通过累加时间 time 和更新高度 height,直到高度 height 达到或超过井深 N 时停止。
时间复杂度
- 最坏情况下,蠕虫需要爬行接近井深的高度,循环次数与井深
N和爬升净增量(U - D)相关。 - 每次循环执行常数次操作,因此时间复杂度为 O(N / (U - D)),即线性级别。
- 由于题目限制
N ≤ 100,该算法在常数时间内即可完成。
注意事项
- 边界条件 :循环中使用
height >= N作为终止条件,确保蠕虫在上爬过程中头部到达井口即完成任务,符合题目要求。 - 时间计数 :每次上爬和下滑均计为 1 分钟,且
time在循环开始时即自增,保证了"不足 1 分钟按 1 分钟计"的约定。 - 输入保证 :题目已给定
D < U,因此蠕虫每两个分钟净上升U - D寸,保证最终能够爬出井。 - 变量初始化 :
time与height初始化为 0,对应蠕虫从井底开始。 - 代码简洁性 :使用
while (1)无限循环配合break,使逻辑清晰易读。