☰
OJ基础题题解使用指南:从输入输出到算法入门
2026/10/31 5:08:38 网站建设 项目流程

简介:这份资料面向准备北京大学POJ在线评测与ACM算法训练的学习者,收录一批基础题目的C++实现答案,适合刚接触算法竞赛、需要对照思路巩固语法与常见算法的读者。压缩包共157个文件,其中156个为cpp源码,另有1个txt说明文件,整体约59KB,体积轻便,便于按题号整理和本地编译运行。资源已有2653人学习下载,说明其在入门刷题场景中具有一定参考价值。读者可借助这些代码查看输入输出处理、循环与数组、模拟、简单数论、动态规划及搜索等题型的实现方式,并对照OJ判题结果排查边界条件与格式错误;由于以源码为主,更适合作为个人练习后的参考与思路比对,而非直接提交。

1. 先搞懂一个概念:在线评测题库和“题解”到底是什么

很多人第一次打开这类资源,反应都差不多:一叠按编号命名的源文件,点开全是代码,读三行就关掉了。这很正常——它更像习题册背后的答案页,而答案本身不会告诉你题目在问什么。所以先把概念说清楚:有一类网站叫在线评测题库,上面挂着大量编程题,你在本地写好程序提交上去,服务器拿预设的测试数据跑一遍,对就通过,错就告诉你是哪一类错。这份资源,就是其中一部分基础题目的参考答案集合,语言以 C/C++ 为主,难度集中在上手阶段。它适合刚学完一门语言的语法、想找题练手、又不知道从哪道题开始的新手,属于那种“照着敲一遍就有收获”的入门材料。

2. 为什么零基础也要从基础题开始:把语法变成手感

学编程最容易卡住的地方,通常出现在“我刚看完语法书,接下来该干嘛”这一步。变量、循环、条件判断,书上都懂,合上书想写个小程序,手指头就停在键盘上方不动了。刷基础题正好填上这个缝:它给你一个具体到不能再具体的小任务,你只要把这个任务翻译成代码,然后交给一台不知疲倦的机器去判断对错。

2.1 语法书看十遍,不如让判题机给你一次通过

看书是输入,写代码是输出,中间隔着一道很难自己跨过去的坎。你在书里看到for循环,觉得自己完全理解了,可题目要求“读入 n 个数,求和后输出”,你可能立刻卡在三个地方:n 怎么读、数存哪儿、循环从 0 开始还是从 1 开始。这些细节,书里通常一句话带过,只有自己写才会暴露。

判题机的好处是它不会照顾你的情绪。你的程序对就是对,错就是错,而且会告诉你错在哪一类。这种即时、客观、不讲人情的反馈,是新手阶段最稀缺的东西。我见过太多人学了半年语法,写不出一段完整的、能跑通输入输出的程序,问题不在智力,而在于从来没被“判”过。

所以别把刷基础题当成考试,把它当成练手感。就像学游泳,岸上把动作要领背得再熟,下水那一下还是得自己扑腾。第一道题通过时那声“通过”,比看十页教程都提神。

2.2 一份现成的答案集,省下的是“卡壳时间”

新手做题卡壳,其实分三种情况,得分开对待。

第一种是完全没思路,看完题面不知道从哪下手。这种在基础题里不算多,因为基础题的题意通常很直白。第二种是有思路但写不出来,知道要循环、要判断,就是不知道怎么组织成代码。第三种是写出来了但过不了,本地跑着自己造的样例没问题,提交上去被判错。第二种和第三种,一份可运行的参考答案能帮上大忙——它把“想法”和“能跑的代码”之间那段空白填上了,你能直接看到别人是怎么组织循环、怎么定义变量、怎么处理输入的。

但这里有一条血泪经验:答案不是用来抄的,是用来对照的。抄一遍交上去通过,第二天换一道同类型的题,你还是不会。因为抄的过程里你只是搬运字符,脑子里没有发生“翻译”这件事。正确的用法后面第 4 章会细讲,这里先记住一句话:先自己撞墙,再看答案,看完还要默写一遍。

2.3 基础题到底在练什么:其实是三件事

很多人以为基础题就是练语法,其实不是。语法只是入场券,真正反复练的是三件事。

第一件是输入输出的处理。这是新手翻车最集中的地方:题目到底给一组数据还是多组?多组的话什么时候停?输出要不要换行,末尾要不要多一个空格?这些问题在真实项目里也天天遇到,只是形式不同。基础题把它们压缩成最小模型,逼你养成“先看清输入输出格式再动手”的习惯。

第二件是基本数据结构的用法。数组怎么开、开多大、下标从几开始,字符串怎么读、怎么比较,结构体怎么把几个相关的值打包在一起。这些东西单独讲很枯燥,放到题目里就有了意义。比如一道“统计每个数字出现几次”的题,你自然就理解了“数组可以当计数器用”这件事,比背定义有效得多。

第三件,也是最容易被忽略的一件:把一段自然语言描述翻译成一步步可执行操作的能力。题面说“把序列里相邻的相同元素合并”,你得先想清楚这是要遍历、要比较、要记录上一个值,然后才是写代码。这个“拆解”的动作,才是编程真正的核心技能,而它只能靠大量的小题目喂出来。

2.4 这份资源能解决什么,不能解决什么

说清楚边界,用起来才不别扭。

它能给你的:一批基础题的参考实现,可以直接编译运行的完整代码;常见的输入输出写法套路,比如多组数据读到文件结尾怎么写、给了组数怎么写;一些边界情况的处理方式,比如 n 等于 0 时怎么办。对刚上手的人来说,这些就是“看得见的台阶”。

它不能给你的:不能代替你思考,代码放在那儿不会自动变成你的能力;不覆盖高难度题目,基础题和算法竞赛题之间还有很长一段路;也不保证是写法最优、风格最好的版本,参考实现的意义在于“能跑通、思路清楚”,而不是“教科书级范例”。

提示:把这份资源当成“答案册”,而不是“教材”。教材告诉你该学什么,答案册只在你做完题之后告诉你差在哪。顺序反了,效果会差很多。

3. 第一个例子怎么跑:从读题到提交的完整流程

理论说完了,接下来动手。这一章的目标很单纯:让你在半小时内,把第一段代码提交上去,并且看到那个让人心情变好的结果。整个过程分四步——准备工具、读题、写代码、本地自测,最后才是提交。

3.1 先把工具准备好:一个能编译能运行的最小环境

不需要复杂的开发环境,两样东西就够:一个顺手的代码编辑器,用来写文件;一个命令行里的编译器,用来把代码变成能跑的程序。

Windows 上通常装一个带编译器的集成环境,或者单独装编译器再把它的路径加进系统环境变量;macOS 和 Linux 一般自带编译器,打开终端就能用。装完之后,在命令行里敲一句确认:

g++ --version

如果屏幕上打印出编译器的版本信息,说明能用了。如果提示“找不到命令”,那就是路径没配好,回头检查安装步骤,别在这一步硬扛——这是新手第一个容易放弃的地方,其实只是环境变量没生效。

接下来建一个自己的文件夹,比如叫oj,以后每道题在里面建一个源文件,命名随便,a.cpp、sum.cpp都行。养成“一道题一个文件”的习惯,比全部堆在一个文件里改来改去清楚得多。

注意:不要用中文路径,也不要在文件名里加空格。某些环境下这类路径会让编译命令莫名其妙地失败,排查起来非常费劲。

3.2 读题的三个固定动作:输入、输出、边界

读题不是“看一遍”,而是有固定套路地看三遍。养成这个习惯,能省掉后面一大半的调试时间。

第一遍看输入:给几组数据?第一行有没有一个数字表示组数?每组数据有几个值?值的范围多大,需不需要用更大的整数类型?有没有明确说“输入以文件结束为终止”?

第二遍看输出:每组结果单独一行还是用空格隔开?末尾有没有多余空行?大小写有要求吗?保留几位小数?

第三遍看边界:n 最小可能是多少?会不会是 0?会不会有负数?最大值多大,会不会超出普通整数范围?

举个最常见的例子。题面写“输入两个整数,输出它们的和”,看起来一句话说完,但实际数据是好几组、一直给到文件结束。很多新手按“只读一组”写完提交,被判错,然后盯着代码看半小时也看不出问题——因为代码没错,是他把输入模式看漏了。

3.3 第一个能过的程序:两数相加的多组写法

假设题目就是“多组数据,每组两个整数,输出和,每组一行”。参考实现长这样:

#include <cstdio> int main() { int a, b; // scanf 返回成功读入的变量个数,读到文件结尾时会小于 2,循环自然结束 while (scanf("%d %d", &a, &b) == 2) { printf("%d\n", a + b); // 每组结果单独一行,行末的换行不能省 } return 0; }

逐行说清楚。第一行把标准输入输出库引进来,scanf和printf都在里面。int a, b;定义两个整型变量,用来装这一组数据。关键是while那一行:scanf本身有返回值,它返回“成功读到了几个值”,这里要读两个值,所以写== 2。当输入数据读完,scanf读不到东西,返回值变成小于 2 的数,条件不成立,循环结束。这就是“读到文件结尾为止”的标准写法。

printf("%d\n", a + b);里的%d是整数的占位符,\n是换行。别小看这个\n,它决定了你的输出是不是“每组一行”,漏掉就是格式错误。

如果题目的输入模式换成“第一行给一个数字 T,表示有 T 组数据”,写法就变了:

#include <cstdio> int main() { int t; scanf("%d", &t); // 先读入组数 while (t--) { // 循环 t 次,t-- 是先用再减 int a, b; scanf("%d %d", &a, &b); printf("%d\n", a + b); } return 0; }

while (t--)这个写法新手常看不懂,拆开就是:判断 t 是不是非零,是就进循环体,同时把 t 减 1。t 从 5 开始,循环体执行 5 次。两种输入模式的差别,是新手第一个大坑——代码结构完全不同,判题结果却都是“答案错误”,光看错误提示根本猜不到原因。

3.4 本地自测:先过自己造的样例,再交给判题机

写完了别急着提交。先在本地造一组输入,把程序跑一遍,看看输出对不对。建一个文本文件in.txt,写两行:

1 2 3 4

然后在命令行里编译并运行:

g++ -O2 -Wall -o sum sum.cpp ./sum < in.txt

第一行是编译。-O2打开优化,程序跑得更快,很多题目的时间限制靠它才过得去;-Wall打开常用警告,它会提醒你“变量没初始化”“类型转换可能丢精度”这类问题,非常值得开。-o sum指定输出的程序名叫sum。第二行是运行,< in.txt表示把文件内容当作程序的输入喂进去。

如果屏幕上出现3和7两行,说明逻辑对了。接下来再补两组边界测试:输入0 0看输出是不是0;输入一个很大的数,看会不会溢出。这些额外样例不需要提交,纯粹是给你自己排雷。

3.5 提交之后:那张判题结果到底在说什么

把代码贴进提交框,等几秒,屏幕上会返回一个结果。新手第一次看基本是懵的,先记住这张对照表:

判题结果它想告诉你什么第一件事去查什么
通过所有测试数据都过了可以去看别人的写法,比较风格差异
答案错误程序跑完了,但某些数据的结果不对输入模式、边界值、整数范围
格式错误结果大概率是对的,输出格式不对行末换行、多余空格、空行
超时结果可能对,但跑得太慢有没有多余的循环,读入方式是否太慢
运行错误程序中途崩了数组越界、除以零、递归太深
编译错误代码根本没编译成功看编译器给的行号和报错信息

最值得说的是“格式错误”和“答案错误”的区别。前者说明你思路对了,只是排版没对上,改一个换行符可能就过了;后者才是逻辑问题。很多人看到不是“通过”就慌了,其实这两种情况的排查方向完全相反。看懂这张表,你就有了排查的起点,而不是对着一屏代码干瞪眼。

4. 把一份题解集用出价值:对照、复盘、二次默写

拿到答案集,最常见的错误用法是“不会就翻,翻到就抄,抄完就下一题”。这样刷二十道,水平和不刷差不多。真正有效的用法有一套固定流程,虽然慢一点,但每一步都在往你脑子里装东西。

4.1 十五分钟原则:先自己撞墙,再看答案

给自己定一条硬规矩:一道题,先独立想十五分钟。这十五分钟里可以翻笔记、可以查语法、可以在纸上画,就是不许打开答案。

为什么是十五分钟?太短了,你还没把题目在脑子里过一遍;太长了,新手容易陷进去出不来,一小时耗在一道基础题上,性价比太低。十五分钟是个折中点,足够你尝试一两种思路并且失败一次。

十五分钟之后还写不出来,就去看答案。这时候看和一开始就看,效果完全不同——你脑子里已经有了一堆“为什么这样不行”的疑问,答案的每一行都在回答这些疑问,信息吸收率会高很多。

我第一次按这个规矩做题时,前几道全是十五分钟就投降。但做到第十道左右,我发现自己在看答案之前已经能猜到大概思路了,那种感觉很实在。

4.2 看懂一份答案,要问自己四个问题

答案摆在面前,别急着抄。先回答四个问题,答不上来就说明还没看懂。

第一个问题:这道题到底在考什么?是考输入输出的处理,还是考数组的用法,还是考某个简单的模拟过程?想清楚这一点,你才知道该记住什么。

第二个问题:关键变量是哪几个?一份能跑的代码里,总有一两个变量承担了核心作用,比如计数器、当前最大值、上一个读到的值。找到它们,再看它们在哪里被修改。

第三个问题:边界是怎么处理的?特别注意那些看起来“多余”的判断,比如if (n == 0)、循环写成i < n - 1。这些地方往往就是新手会漏掉、导致被判错的关键点。

第四个问题:如果让我自己写,我会在哪一步卡住?把这一步单独拎出来,那是你这道题真正的收获。

四个问题答完,你才算“读”过这份答案,而不只是“看”过。

4.3 二次默写:把“看懂”变成“会写”

合上答案,新建一个空文件,从零把这道题再写一遍。不许复制粘贴,不许偷偷瞄。

这个过程会很挫败,因为你会发现刚才明明看懂了,写的时候还是卡在scanf的返回值上、卡在循环的边界上。但正是这些卡住的地方,才是你真正没掌握的地方。写完之后编译、跑样例、和答案对比,找出差异,再写第三遍。

一般来说,同一道题默写两到三遍,基本就长在脑子里了。之后再遇到同类型的题,你会发现自己不用想就能写出输入输出的框架,注意力可以全部放到逻辑上——这就是所谓的手感。

提示:默写的时候刻意把变量名改成自己的习惯写法,不要照搬答案里的名字。改名字这个动作会强迫你理解每一行在干什么,抄名字则不会。

4.4 建一个自己的错题本

不用很正式,一个文本文件就行。每道做错或者卡住的题,记三样东西:

  • 题目编号加一句话题意,方便以后回看时快速回忆;
  • 我错在哪,写具体,比如“把多组数据写成了只读一组”“数组开小了”;
  • 正确做法的关键一步,一句话,比如“先读组数 T 再循环”。

积累到二三十条之后,你会发现错误在重复。翻一翻错题本,看看哪类错误出现了三次以上,那就是你下阶段要重点练的方向。这比漫无目的地刷题高效得多,也是我认为新手最值得养成的一个习惯。

5. 新手最容易踩的五个坑:现象、原因和解决办法

这一章讲的全是我见过、也自己踩过的坑。按“现象 → 原因 → 解决”排,遇到时对着查,比自己瞎猜快得多。

5.1 坑一:本机跑得好好的,提交就是答案错误

现象:自己造了几组样例,输出全都对,提交上去却反复被判答案错误,改来改去也没用。

原因:最可能是把输入模式看漏了。你手上造的样例只有一组数据,而题目的真实数据是多组,你的程序只处理了第一组就结束了。第二种可能是数据范围超出了int,题目给的数到十亿级别,两个一加就溢出了。第三种可能是题目有隐藏的边界,比如 n 可以是 0、可以有负数。

解决:先回到题面,逐字确认输入格式,尤其注意“多组”“以文件结束为终止”“第一行是组数”这类描述。然后把整数换成范围更大的类型试试,把边界值 0、1、最大值都造一遍跑跑看。养成提交前先造三组样例的习惯,其中至少一组是边界。

5.2 坑二:结果明明对,却被判格式错误

现象:判题结果不是答案错误,而是格式错误。你自己看输出,数字都对,怎么看都不像有问题。

原因:输出格式的细节没对上。常见的有三种:每组结果后面漏了换行,全部挤在一行;多组数据之间多打了空行;行末多了一个空格。这些在屏幕上肉眼几乎看不出来,但判题程序是逐字符比对的,差一个空格就是错。

解决:把题目的输出说明再读一遍,确认是“每组一行”还是“空格分隔”。如果实在看不出来,试试在每组输出后统一加换行,或者去掉末尾多余的空格。有时候改一个\n就过了,别怀疑人生,这是最常见的翻车方式之一。

5.3 坑三:多组数据只处理了第一组

现象:程序能跑,第一组数据的答案是对的,后面的全错,或者干脆只输出了一行。

原因:输入循环写错了。要么根本没有循环,只读了一次;要么循环条件写成了while (1)却没有退出条件,程序卡死;要么把“先读组数 T”和“读到文件结束”两种模式搞混了,用错了框架。

解决:先看题面属于哪种模式。给了组数 T 的,用先读 T 再循环 T 次的写法;没给组数、只说多组数据的,用scanf返回值判断。两种框架别混用,这是两道完全不同的模板,写之前先确定用哪个。写完拿两组数据测一下,如果只输出一行,基本就是这个问题。

5.4 坑四:数组开小了,程序跑着跑着就崩了

现象:本地小数据测试完全正常,提交大数据就报运行错误,或者自己测试时程序突然退出、输出一堆乱码。

原因:数组开小了,或者下标越界。题面说 n 最大到一万,你开了 1000 的数组,数据一大就越界写入,覆盖掉别的内存。还有一种情况是循环写成i <= n,而数组只有 n 个元素,多访问了一位。

解决:把数组开得比题目给的最大值大一点,比如最大一万就开一万零五,留点余量,多开几个元素不占多少内存,但能省掉很多玄学问题。循环边界统一用<而不是<=,除非你非常确定要多算一位。写完顺手检查一遍每个数组的声明和每个循环的上界。

5.5 坑五:答案抄过去了,换道题还是不会

现象:答案集里的题,照着敲都能通过,正确率看着挺高。可一关掉答案,换道同类型的新题,还是不知道从哪下手。

原因:抄写这个动作只动手指,不动脑子。你没有经历“从题面到思路”的翻译过程,也没有经历“从思路到代码”的搭建过程,跳过了最难也最有价值的两个环节。

解决:回到第 4 章那套流程——十五分钟原则、四个问题、二次默写。慢是慢,但每道题都会留下东西。宁可一周只做五道题并全部默写通过,也不要一天抄二十道。这个道理听起来像老生常谈,但真正做到的人不多,做到了的人进步速度差别非常明显。

6. 下一步学什么:从基础题到算法入门的路线

把基础题刷顺之后,很多人会陷入第二个迷茫期:题会做了,但不知道下一步往哪走。这里给一条我自己走过的路线,按顺序来,不用跳。

第一阶段,把“输入输出 + 数组 + 字符串”这三样练到不用想。目标是看到题面就能立刻判断输入模式、立刻确定数据用什么存。这个阶段大概需要二三十道题,重点不是难度,是熟练度。

第二阶段,进入排序和查找。手写一遍冒泡或选择排序,再用语言自带的排序函数写一遍,比较两者的差别;然后练二分查找,理解“有序”这个前提为什么重要。这个阶段开始有“算法”的味道了。

第三阶段,接触贪心和简单的模拟题。贪心的核心是“每一步都选当前看起来最好的”,题目通常不难想,难在证明,入门阶段不用纠结证明,先把能过的写出来。

第四阶段,递归与简单的搜索。从求阶乘、斐波那契入手,再过渡到“走迷宫”这类需要回溯的题。这个阶段会第一次真正体会到“函数调用自己”是怎么回事。

第五阶段,最基础的动态规划。从数字三角形、最长上升子序列这类经典入门题开始,理解“把大问题拆成小问题并记录结果”这个思路。

阶段主要练什么大致题目量判断自己过关的标准
一输入输出、数组、字符串20~30 道看题就能定输入模式,不用试错
二排序、二分查找15~20 道能说清每种排序的差别和适用场景
三贪心、模拟15~20 道能把题面步骤一条条翻译成代码
四递归、简单搜索15~20 道能画出递归的展开过程
五基础动态规划10~15 道能自己写出状态和转移式

再说一个具体技巧:每进入一个新阶段,先找两道最简单的题“探路”,把这一类的代码框架默写熟,再往上加难度。别一上来就挑标着高难度的题,那只会让你怀疑自己不适合学编程,而问题其实出在选题上。

最后说说我自己的教训。刚开始刷题那阵,我特别爱看答案,看完觉得“哦原来是这样”,然后心安理得地下一题。一个月下来做了六十多道,实际掌握的可能不到十道。后来改成每道题必须默写一遍才算过关,进度一下慢到一周五道,但两个月后再回头做以前的题,基本都能独立写出来。从那以后我每次做题都强制走一遍“先想十五分钟、再看答案、合上默写”的流程,再也没跳过。慢一点真的没关系,怕的是原地转圈还以为自己在前进。

这份基础题答案集,就当是你练手时的参考答案册,别供着,也别抄。挑一道最简单的,打开编辑器,敲下第一行#include,跑通它,你会明白那种感觉。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询