PAT乙级1107老鼠爱大米:输入顺序与最大值判断的经典易错题解析

PAT 乙级 1107 这道题,刷过的人应该都有印象:题面叫“老鼠爱大米”,看起来相当生活化,代码量也很短,但它不是那种轻松白送的送分题。我当年第一次做的时候就栽在最后一行的读入顺序上,本地样例全部通过,一提交就 WA,排查了半天才意识到问题根本不在算法,而在输入流的调用顺序不对。这也正是我从“看懂题目”到“真正会做”之间踩过的最值得记录的一步。

这道题本质上是“分组求最大值 + 存在性判断”,非常适合刚学完循环和数组的初学者拿来练手,也适合正在备考 PAT 乙级的人在考前快速复盘读入输出这类基本功细节。如果你已经开始刷 PAT 乙级题库,1107 是你绝对绕不开的一道经典题。接下来我按照自己的理解,从破题、思路选型、代码实现、常见坑这几个角度完整拆一遍。

1. 题目到底在问什么:先破题再动手

1.1 一组大米一个最大值

题面会给你两个正整数 N 和 M,N 代表小组数量,M 代表每个小组里的大米粒数。接下来的 N 行里,每行有 M 个整数,代表每一粒大米的重量。任务分两部分:第一,把每个小组里最重的那一粒找出来;第二,把这些“各组最大值”汇总起来,判断其中是否存在一个值等于最后给出的目标值 K。

举个简单的例子,假设输入是:

3 4 12 5 8 10 20 18 6 9 7 3 15 11 10

这里 N=3,M=4。第一组最大值是 12,第二组是 20,第三组是 15,所以第一行输出就是12 20 15,然后判断这些最大值里是否存在一个数等于最后给的 10。12、20、15 都不等于 10,所以输出 NO。如果最后给的是 20,那么结论就是 YES。

这个逻辑看起来简单到不需要多说,但真正在考试里丢分的点,恰恰藏在最后那个 K 的位置上。

1.2 藏在最后一行里的“目标值”

这道题最有迷惑性的地方,就是目标值 K 出现在所有成绩数据之后。很多人第一眼看到题,觉得无非就是“找最大值 + 判断存在性”,于是随手写出代码:先读 N 和 M,再循环读每一组,求完最大值就顺手和 K 比较。问题来了——K 此时还没有被读进来。

在 C 语言里,如果变量 k 没有被赋值就直接参与比较,它的值是未知的,可能是上一次内存残留的随机值。本地跑的时候偶尔碰巧和预期一致,但一提交就大面积 WA。这个现象我在各个刷题群里见过不止一次,几乎每届考生都会有人掉进同一个坑里。

另一个表层问题是“行”的概念。在 scanf 看来,空格、换行、Tab 都是统一的空白字符,它读取数据时并不关心你在哪一行。所以“最后一行给出 K”这个描述,在代码层面其实是“整数流中的最后一个整数”。如果你用循环去读 N 行、每行 M 个整数,那么循环结束后下一个 scanf 自然就会读到 K。这个顺序不能乱,乱了就是全盘崩塌。

2. 核心思路选型:为什么要“存”而不是“边读边判”

2.1 方案对比:二维数组、最大值数组、查表数组

我第一次做这题时,第一反应是开一个二维数组把所有数据存下来,再统一处理。后来发现完全没必要。这里我把三种常见思路放在一起对比一下,大家可以根据自己的习惯选。

方案核心做法优点缺点
二维数组全存先用二维数组存下所有分数,再逐组求最大值思路直观,符合第一反应浪费空间,代码变长,没必要
最大值数组边读边求每个小组的最大值,存入一维数组,最后统一判断空间开销小,逻辑清晰,推荐需要多开一个一维数组
布尔标记数组把各组最大值作为索引打标记,读入 K 后直接查表判断变为 O(1),思想更进阶需要知道分数范围,可能有越界风险

坦白说,这道题三种写法都能 AC,但“最大值数组”是我最推荐的一种。它既不浪费空间,又完全顺应题目的输入顺序:你无法在读到 K 之前判断,但只要先把各组最大值留存在数组里,读入 K 之后随时可以重新遍历判断。

2.2 读入顺序才是真正的考点

你已经看出来了,这道题真正的核心考点不是“怎么求最大值”,而是“怎么安排读入顺序”。很多人只盯着算法本身,忽略了输入流里的先后关系,结果被一个简单的顺序问题卡住。

我用一句话概括正确流程:

  • 读入 N 和 M。
  • 循环 N 次,每次内层循环 M 次,读入每个成绩,实时比较得到本组最大值。
  • 把每组最大值存进数组。
  • 循环结束后,读入目标值 K。
  • 先按要求输出各组最大值,再遍历最大值数组判断是否存在等于 K 的值。

每个环节都不能提前或延后。尤其是读 K 的这步,如果你在求最大值的过程中就试图拿 K 来比较,那么 K 还未被赋值;如果你在读取第一组数据前就去读 K,那么读到的其实是第一组的第一个成绩。这两种错误在本地测试时都不容易暴露,因为它们需要特定输入才会显现,这也是这种“简单题”容易让人翻车的原因。

3. 完整 C 语言实现与逐步讲解

3.1 可复现代码:最大值数组法

直接上一份可以编译运行的 C 语言代码,这也是我最终提交的版本:

#include <stdio.h> int main() { int n, m, k; scanf("%d %d", &n, &m); int maxs[105]; // 题目范围一般不大,105足够 for (int i = 0; i < n; i++) { int max = -1; // 初始化为比任何成绩都小的值 for (int j = 0; j < m; j++) { int score; scanf("%d", &score); if (score > max) { max = score; } } maxs[i] = max; } scanf("%d", &k); for (int i = 0; i < n; i++) { if (i > 0) { printf(" "); } printf("%d", maxs[i]); } printf("\n"); int flag = 0; for (int i = 0; i < n; i++) { if (maxs[i] == k) { flag = 1; break; } } printf("%s\n", flag ? "YES" : "NO"); return 0; }

这段代码的核心逻辑很清晰,但有几个细节值得单独展开讲。

3.2 关键细节一:max 的初始值为什么是 -1

题目里的成绩是整数,而且通常是非负的。有人会把 max 初始化为 0,这在绝大多数情况下都没问题,因为如果读到的是正数,第一次比较必然更新 max;如果整个小组所有成绩都是 0,那么 max 保持 0,也是正确结果。

但把 max 初始化为 -1 是一个更严谨的习惯。理由很简单:它不假设成绩的最小值一定是 0。万一题目把成绩范围调整为包含负数的情况,-1 依然能保证第一次读入的数据一定比 max 大,从而正确赋值。养成这个习惯之后,你会少踩很多“初始值选错导致答案整体偏差”的坑。

3.3 关键细节二:输出格式的空格控制

PAT 这类题目对输出格式要求非常严格,空格多一个、少一个都算格式错误(PE)。常见的输出要求是“各组最大值之间用空格分隔,行末不能有多余空格”。这行要求看着简单,但真写起来,很多人都会在最后一个数字后面多打一个空格。

我的做法是:第一个数字前面不加空格,从第二个数字开始,每个数字前加一个空格。所以在代码里用if (i > 0) printf(" ")来判断。这样最后一个数字后面不会出现空格,完全符合要求。

如果你看到别人的代码里有printf("%d ", maxs[i])这种写法,后面再单独退格,那是很不推荐的,不仅逻辑绕,而且容易在判题时触发格式错误。

3.4 Python 版对照与思路验证

有些同学习惯先用 Python 快速验证思路,再回 C 语言里实现。这里也给一个 Python 简版,方便对照理解:

n, m = map(int, input().split()) maxs = [] for _ in range(n): nums = list(map(int, input().split())) maxs.append(max(nums)) k = int(input()) print(" ".join(map(str, maxs))) print("YES" if k in maxs else "NO")

Python 的 input() 天然按行读取,所以“行”的语义会比 C 语言更直观一些,但核心逻辑完全一致:先把各组最大值存进列表,再读 K,最后统一判断。用这个版本跑通思路之后,再去写 C 版,就不容易在逻辑层面出错了。

4. 常见错误与排查实录

4.1 我踩过最深的三个坑

下面这三个坑,我在刷题群和日常辅导里几乎每年都会看到,自己当年也亲身踩过,值得单独记录一下。

第一个坑:读 K 的位置放错。有人觉得反正 K 最后才用,干脆在循环里顺手比较。错误代码类似于:

for (int i = 0; i < n; i++) { int max = -1; for (int j = 0; j < m; j++) { scanf("%d", &score); if (score > max) max = score; } if (max == k) flag = 1; // 错:k 还没有被读入 }

这里的 k 是未初始化的变量,在 C 语言里它的值是未定义的。本地跑的时候,可能碰巧和某个最大值不相等,flag 保持 0,你甚至察觉不到问题。但提交到在线评测系统后,结果就会飘忽不定,大概率是 WA。

第二个坑:先去读 K。有人为了让“边读边判”成立,把scanf("%d", &k)放在了所有成绩读取之前。这样做的话,程序读到的所谓“k”,其实是第一组的第一个成绩。后续所有成绩都会错位,最终解析出来的 N 行数据全是乱的,输出自然不对。

第三个坑:输出多了一个空格。这是最常见的格式错误。例如用printf("%d ", max)输出每个最大值,然后在最后单独处理换行,结果行尾多出一个空格,提交后直接 PE。这类错误不算算法问题,但同样会让你丢分,而且有时候比 WA 更难察觉,因为它只在你仔细比对输出时才会被发现。

4.2 区分 WA 与 PE:从判题反馈定位问题

在 PAT 这类在线评测系统里,提交后通常会有“答案正确”“答案错误”“格式错误”等不同反馈。很多新手一看到非 AC 的结果就慌,其实不同反馈已经给了你足够多的信息。

  • 如果是“格式错误(PE)”,优先检查空格、换行、大小写这些输出细节。不要怀疑算法,只要输出完全符合要求,这个反馈基本就会消失。
  • 如果是“答案错误(WA)”,那么大概率是逻辑或读入顺序问题。这时候不要盲目看代码,先拿几个手算样例跑一遍,尤其构造一个所有最大值都不等于 K 的用例,再看输出是否正确。
  • 如果是“段错误”或“运行时错误”,在这道题里基本不用考虑,除非你数组开得太小或者访问越界。

我见过不少人看到 WA 就疯狂改算法,结果越改越乱。其实只要冷静分析一下,很多 WA 都出在读入顺序这种“看起来不太起眼”的地方。

4.3 本地调试建议:打印中间结果

新手阶段我非常推荐用“printf 调试法”。在这道题里,你可以在读入 K 之后、输出之前,打印所有中间变量:

#ifdef DEBUG for (int i = 0; i < n; i++) { printf("maxs[%d] = %d\n", i, maxs[i]); } printf("k = %d\n", k); #endif

本地编译时通过定义 DEBUG 宏开启这些打印,提交前注释掉即可。这样做的好处是,你可以直观地看到程序读到的 K 到底是什么、各组最大值是否计算正确。这比盯着代码发呆要高效得多。

我个人的习惯是,凡是涉及“多个数据先后读入”的题,都会在本地打印一遍读入结果。因为读入一旦错位,后面的所有逻辑都是空中楼阁,你怎么调都调不对。

5. 从 1107 延伸出去:这类题型的通用模板

5.1 分组统计与存在性判断的模板

做完 1107 之后,我意识到这类“分组求最值 + 存在性判断”的题,在 PAT 乙级里到处都是。它们的共同点是:

  • 输入先给若干组数据,每组若干个数。
  • 每组都要求出一个统计量,比如最大值、最小值、平均值。
  • 最后给出一个额外条件,要求判断所有组的统计结果中是否存在满足条件的值。
  • 目标条件往往放在最后,导致必须先读完所有数据再判断。

于是我把这类题的代码框架总结成了一个模板,后面遇到类似的题直接套:

// 模板框架 scanf("%d %d", &n, &m); for (int i = 0; i < n; i++) { int current = 初始值; for (int j = 0; j < m; j++) { scanf("%d", &x); // 根据题目要求更新 current } results[i] = current; // 保存当前组的统计值 } scanf("%d", &target); // 额外目标值,注意位置不能乱 // 输出与判断

这个模板的复用价值很高。比如把求 max 换成求和、求平均,把“存在相等”换成“存在大于”,只需要改两三个地方,核心框架完全不用动。

5.2 简单题里的细节陷阱

PAT 乙级里其实没有太多算法难度特别高的题,很多人丢分全部丢在“看起来会做”的题上。1107 就是一个典型例子:它考察的不是高深的算法,而是你是否能在简单的流程里保持对输入输出细节的敏感。

我在备考过程中养成了一个习惯:只要看到“先给一批数据,再给一个关键值”这种输入顺序,就会先把读入顺序在草稿纸上写一遍,再开始写代码。不要嫌这一步多余,因为很多“简单题”如果不在动手前想清楚读入顺序,写完之后再排查耗时反而更多。

针对 PAT 乙级,我还会整理一份“易错点清单”,内容包括:scanf 的调用顺序是否和输入顺序一致、数组初始值是否覆盖所有合法输入、输出行末是否会有多余空格、循环边界是否存在差一错误。每次考试前看一遍这个清单,比临时刷好几道新题都管用。

写在最后的个人体会

如果要说我从 1107 这道题里收获最大的是什么,那一定不是“求最大值的方法”,而是“在写代码前先确认数据流顺序”的意识。这道题让我真正理解了:在线评测题目不会很复杂,但它会把你对基本功的掌握程度暴露得干干净净。

尤其对于正在备考 PAT 乙级的朋友,我建议你不要急着刷难题,先把这些“简单但容易错”的题按类型整理好,反复练习读入、输出、边界处理这些基本功。等你把这些细节练到条件反射的地步,再去面对中等难度的题目,你会发现真正的思考空间要大得多。

最后再分享一个小技巧:刷这类题时,本地多写几组边界用例。比如 N=1、M=1,比如所有成绩都是同一个值,再比如 K 恰好等于某一个最大值。把这些边界情况跑通,你的代码才算是真的稳了。

相关新闻

Meshroom三维重建安装教程:从显卡驱动到跑通第一个项目

Meshroom三维重建安装教程:从显卡驱动到跑通第一个项目

简介&#xff1a;Meshroom是一款基于AliceVision框架的开源三维重建软件&#xff0c;面向建筑测绘、考古记录、虚拟现实与游戏设计等场景的建模爱好者与从业者。它无需专业3D扫描设备&#xff0c;仅凭多角度普通照片即可通过摄影测量技术自动完成特征匹配、点云生成、网格重建与…

2026/10/20 11:42:39 阅读更多 →
ARM编译器版本5交叉编译环境搭建与避坑指南

ARM编译器版本5交叉编译环境搭建与避坑指南

简介&#xff1a;ARM编译器版本5是ARM公司面向ARM架构处理器推出的优化编译工具&#xff0c;适用于嵌入式系统开发、底层驱动编写与性能调优场景&#xff0c;尤其适合需要兼顾代码效率与资源占用的中高级开发者。资源包共3个文件&#xff0c;以zip压缩包形式提供&#xff0c;整…

2026/10/20 11:42:39 阅读更多 →
Fetch API实战指南:从基础请求到项目级封装

Fetch API实战指南:从基础请求到项目级封装

1. 从一个真实翻车现场说起&#xff1a;为什么我换掉了XMLHttpRequest先说一件小事。前阵子帮人维护一个老系统&#xff0c;列表页有个导出功能&#xff0c;前同事用XMLHttpRequest写了一大段逻辑&#xff1a;监听onreadystatechange、判断readyState 4、再判断status、还要处…

2026/10/20 11:42:39 阅读更多 →

最新新闻

Spring Boot社区在线问诊系统实战:从需求到部署的完整技术拆解

Spring Boot社区在线问诊系统实战:从需求到部署的完整技术拆解

最近后台经常有人问社区家庭医生在线问诊系统怎么做&#xff0c;正好我前阵子完整跟过一个类似项目&#xff0c;从需求梳理到部署上线走了不少弯路。我干脆把这套系统的技术拆解和踩坑记录整理成一篇长文&#xff0c;一方面给自己做个复盘&#xff0c;另一方面给正在做毕业设计…

2026/10/20 13:09:01 阅读更多 →
Git克隆Demo代码仓库实战:从地址到跑通全流程

Git克隆Demo代码仓库实战:从地址到跑通全流程

1. 拿到仓库地址后&#xff0c;先别急着敲命令很多同学第一次接触代码仓库时&#xff0c;最容易犯的毛病就是&#xff1a;复制了地址&#xff0c;打开终端&#xff0c;直接输入git clone&#xff0c;回车&#xff0c;然后开始疯狂刷新浏览器看着进度条发呆。如果仓库小&#xf…

2026/10/20 13:09:01 阅读更多 →
OpenHarmony设备上Flutter淡出过渡动画移植实战与性能优化

OpenHarmony设备上Flutter淡出过渡动画移植实战与性能优化

上个月我把一个原本跑在标准Flutter环境里的页面过渡动画方案移植到OpenHarmony设备上&#xff0c;遇到的第一个问题倒不是动画本身&#xff0c;而是animations 这个官方维护的三方动画库直接编译不过。项目里本来打算用它实现页面切换时的淡出过渡效果&#xff0c;想着省一笔自…

2026/10/20 13:09:01 阅读更多 →
轻量级技能管理方案:从零搭建可量化可组合的技能表

轻量级技能管理方案:从零搭建可量化可组合的技能表

1. 从“skills”这个词说起&#xff1a;它到底指什么“skills”这个词看起来简单&#xff0c;但放在不同语境里&#xff0c;指向完全不同。做招聘的人看到它&#xff0c;想到的是岗位能力模型&#xff1b;做在线教育的人看到它&#xff0c;想到的是课程标签体系&#xff1b;做开…

2026/10/20 13:09:01 阅读更多 →
企业级RAG问答系统实战:知识库、检索链路与大模型应用的完整落地指南

企业级RAG问答系统实战:知识库、检索链路与大模型应用的完整落地指南

做了将近半年的基于大模型的智能问答系统&#xff0c;上线之后我最大的感受是&#xff1a;**决定这套系统好不好用的&#xff0c;往往不是大模型本身&#xff0c;而是知识库和检索链路。**模型答得再聪明&#xff0c;检索不到对的资料&#xff0c;它也只能一本正经地编。我们做…

2026/10/20 13:09:01 阅读更多 →
GraphRAG工程实践:知识图谱如何补足向量检索的推理短板

GraphRAG工程实践:知识图谱如何补足向量检索的推理短板

向量检索失效的那一刻&#xff0c;我才决定认真搞GraphRAG年初做过一个企业内部制度问答系统&#xff0c;刚开始用的是经典的向量库RAG方案&#xff1a;文档切块、embedding、top-k召回、拼prompt喂给大模型。原型阶段跑得很顺&#xff0c;演示的时候领导问了一个问题——"…

2026/10/20 13:08:00 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →