控制流程与数据表示解决的是“程序怎么走、数据怎么放”两个根本问题。很多竞赛题做不出来,不是因为公式不会,而是因为没有先把题面中的对象整理成清晰的数据结构,也没有把处理步骤组织成稳定的执行流程。
学习目标
- 学会把题目中的人物、物资、路线、任务、规则映射成变量和容器。
- 学会用顺序、分支、循环组织程序执行流程。
- 学会在 Python 和 C++ 中选择合适的数据表示方式。
- 学会在写代码前先分析输入输出结构。
概念定义
什么是数据表示
数据表示就是把题面中的信息转成程序能处理的形式。
- 单个对象通常用变量保存,例如数量、价格、时间、距离。
- 一组同类对象通常用列表、数组或
vector保存。 - 需要按名称或编号快速查找时,常用字典、映射表或
map。 - 一条记录包含多个字段时,可以用元组、字典、
struct或类来表示。
什么是控制流程
控制流程就是程序按照什么顺序执行。
- 顺序结构:按步骤依次执行,常见于复杂计算题。
- 分支结构:根据条件选择不同处理方式,常见于等级判定、规则决策。
- 循环结构:重复处理一批数据,常见于统计、模拟和批量更新。
题面如何转成变量和容器
第一步:圈出题目中的对象
以 非遗复杂计算:剪纸原料规格与批量成本核算 为例,题目中的核心对象包括:
- 原料规格
- 单价
- 损耗率
- 批量需求
这些对象在代码中可以拆成:
name或specpriceloss_ratedemand
第二步:判断对象之间的关系
- 如果每条记录结构一样,就存成数组或列表。
- 如果要按规格名查价格,就用字典或映射。
- 如果一条记录有多个字段,就用结构体或字典保存一整条记录。
第三步:确定程序的处理顺序
- 先读入全部数据。
- 再逐条处理记录。
- 最后统一输出结果。
赛项中的出现方式
在复杂计算题中
- 用循环累计成本、产量、路程、税费。
- 用条件判断不同规格、税率和等级。
- 用列表或结构体保存每种商品或材料的数据。
在流程模拟题中
- 用状态变量表示“当前阶段”“当前库存”“当前时间”。
- 用循环推进每一步工序。
- 用条件分支处理异常、停机、补货或规则切换。
在数据管理题中
- 用字典维护编码规则、名称映射和分类统计。
- 用矩阵或二维数组保存纹样、地图、排班表等结构化数据。
- 用校验流程过滤非法输入。
输入输出分析方法
输入分析
写代码前至少要确认以下几点:
- 输入是一条记录、一个表格、一个矩阵还是一个图。
- 每条记录有多少字段,每个字段的类型是什么。
- 是否有多组测试数据。
- 是否可能出现重复、空值、非法值。
输出分析
- 输出是单个数值,还是多项统计结果。
- 输出顺序是否固定。
- 是否要保留小数位数。
- 是否需要输出中间标签、等级或说明。
分步方法
方法一:顺序处理模板
适用于复杂计算和统计题。
- 读入
n条记录。 - 为总和、最大值、分类结果等指标准备变量。
- 在循环中逐条更新结果。
- 统一整理输出。
方法二:规则分支模板
适用于分级、策略推荐和多条件判定题。
- 先把条件按优先级列出来。
- 为每个条件对应一个输出动作。
- 用
if / elif / else或多层条件判断实现。 - 用样例验证每一类分支都能命中。
方法三:状态更新模板
适用于流程模拟题。
- 确定状态变量,例如时间、库存、位置、轮次。
- 明确每一步输入什么、更新什么。
- 按轮次或阶段推进状态。
- 在每一步后检查是否触发边界或异常规则。
Python 实现要点
- 使用
list、dict、tuple表达结构化数据。 - 输入读取优先使用
input().split()、sys.stdin.readline()或sys.stdin.read()。 - 数据量较大时,尽量避免在循环中做过多字符串拼接。
- 排序和统计场景下,列表推导和内置函数很有用,但要确保可读性。
Python 片段示例
records = []
for _ in range(n):
spec, price, loss_rate, demand = input().split()
records.append({
"spec": spec,
"price": float(price),
"loss_rate": float(loss_rate),
"demand": int(demand),
})
total_cost = 0.0
for item in records:
actual_need = item["demand"] * (1 + item["loss_rate"])
total_cost += actual_need * item["price"]
C++ 实现要点
- 使用
vector存批量数据。 - 使用
pair、struct或tuple表示一条记录。 - 注意索引范围、整数溢出和输入输出效率。
- 需要按字段排序时,尽量写清楚比较函数。
C++ 片段示例
struct Material {
string spec;
double price;
double loss_rate;
int demand;
};
vector<Material> records(n);
for (int i = 0; i < n; ++i) {
cin >> records[i].spec >> records[i].price >> records[i].loss_rate >> records[i].demand;
}
常见错误
- 变量含义不清,导致统计维度混乱。
- 把应当放在循环外初始化的变量写进循环里,结果被反复重置。
- 循环边界写错,漏处理最后一条或越界。
- 输入格式和题面不一致,导致读取错位。
- 先更新状态,再判断条件,顺序与题意相反。
与题库 case 的联系
s1-jh-01-heritage-costing
- 练习重点:字段拆分、顺序累计、精度控制。
- 需要先想清楚每种原料对应哪些变量,再做循环统计。
s1-jh-02-heritage-simulation
- 练习重点:状态更新和流程执行顺序。
- 适合训练“每一步发生什么、每一步更新什么”的思维。
s2-jh-03-propagation-sim
- 练习重点:多轮循环、渠道统计和规则触发。
- 适合训练复杂模拟题的变量管理能力。
s4-jh-01-pattern-restore
- 练习重点:矩阵、编码规则和合法性校验。
- 适合训练字典、数组和结构化输出。
训练建议
- 每次做题前先写出“对象表”和“流程表”,哪怕只写在草稿纸上。
- 写完后再回头检查:每个变量的含义是否唯一,每个循环的范围是否准确。
- 如果题目做错,先不要急着改代码,先检查是不是数据表示就建错了。