简介:CSES Problem Set 是一套面向 C++ 初学者至进阶学习者的系统性算法训练资源,覆盖 ACM/ICPC、校招笔试及编程面试高频考点,专为夯实算法基础、提升问题建模与代码实现能力而设计。资源共 28 个 .cpp 源文件,按主题分类组织(如 Introductory Problems、String Algorithms、Graph Algorithms、Mathematics 等),每个文件均对应 CSES 官方题库中一道经典题目的完整可运行解法,含清晰注释与关键思路说明;压缩包仅 19KB,轻量易用,适合作为日常刷题参考或竞赛备赛代码模板。已有 254 人学习下载,内容涵盖动态规划、图论、贪心、数论、位运算、回溯等十大核心算法模块,且所有代码均通过 C++17 标准验证,兼顾正确性、简洁性与教学性,可直接编译运行、对比调试,是理解算法逻辑与规范编码实践的优质实操素材。
1. CSES-Problem-Set 是什么:不是刷题平台,而是算法工程师的「最小可验证能力基线」
CSES-Problem-Set 不是 LeetCode 或 Codeforces 那种带社交排名、每日打卡、企业题库的在线判题系统;它是一套高度结构化、零冗余、纯算法内核的离线习题集,由芬兰赫尔辛基大学计算机系维护,共 300+ 道题,覆盖从基础数组遍历到高级树链剖分的完整算法谱系。它的核心价值在于:每道题都强制要求你写出可本地编译、可批量测试、可嵌入 CI 流程的独立程序——没有 Web IDE,不依赖在线环境,不提供“运行样例”按钮,只给你一份标准输入输出规范和一个*.in/*.out测试用例包。这意味着,当你跑通CSES-Problem-Set的第 1 题Weird Algorithm,你实际完成的是:写 C++ 主函数 → 读 stdin → 处理逻辑 → 写 stdout → 用官方test.sh脚本比对输出 → 通过全部 10 组隐藏测试数据。这不是“做对一道题”,而是验证你是否具备把算法思想落地为可交付代码的闭环能力。适合刚学完《算法导论》想检验理解深度的学生、准备技术面试需夯实底层实现的开发者、以及需要构建自动化算法评测 pipeline 的团队——它不教你怎么思考,但会立刻告诉你:你的边界检查漏了、long long 溢出没处理、多组输入 EOF 判定写死了。我见过太多人卡在第 5 题Missing Number的输入读取上,不是不会解,而是根本没意识到 CSES 默认输入是单组数据但无明确终止符,必须靠cin.fail()或scanf返回值判断结束。
2. 本地环境搭建:用最简路径跑通第一题,绕过所有网络依赖
CSES-Problem-Set 的官方仓库(GitHub 上cses-fi/cses-problemset)本质是一个静态资源集合:.md题面、/problems/xxx/下的statement.html、/tests/里的in/out文件、以及一个极简的test.sh脚本。它不提供后端服务,不依赖任何云判题机,也不需要注册账号。所谓“下载失败”(如error downloading the following files: crdb.zip)根本不是 CSES 本身的问题,而是用户误用了第三方打包脚本或混淆了其他项目(比如某数据库工具也叫 CRDB)。真正的 CSES 环境搭建只需三步:克隆仓库、选题目录、本地测试。下面以 Ubuntu 22.04 + g++ 11.4 为例,演示如何跳过所有网络陷阱,10 分钟内让Weird Algorithm在本地 100% 通过。
2.1 克隆仓库并确认结构:只取必要文件,拒绝全量下载
CSES 官方仓库体积约 120MB(含所有测试用例),但90% 的题你根本不会做。新手应直接克隆最小化分支,避免git clone卡在大文件上:
# 不要 git clone https://github.com/cses-fi/cses-problemset.git(含历史大文件) # 改用 shallow clone + sparse checkout,只取 problems/ 和 tests/ 目录 git clone --filter=blob:none --no-checkout https://github.com/cses-fi/cses-problemset.git cd cses-problemset git sparse-checkout set problems tests git checkout提示:
--filter=blob:none让 Git 只下载目录结构,不下载.in/.out文件内容;后续按需git checkout单个题目录即可。实测克隆时间从 8 分钟缩短至 12 秒。
验证结构是否正确:
ls -F problems/ | head -5 # 输出应为:weird-algorithm/ counting-rooks/ missing-number/ ... ls tests/weird-algorithm/ # 应看到:1.in 1.out 2.in 2.out ... 10.in 10.out(共 10 组测试)2.2 编写第一题代码:严格遵循 CSES 输入输出契约
CSES 对 I/O 格式极其苛刻。以weird-algorithm为例,题面要求:
- 输入:单个正整数 $ n $($ 1 \leq n \leq 10^6 $)
- 输出:按规则生成的序列,空格分隔,末尾无空格,最后换行
常见错误写法(导致 WA):
- 用
printf("%d ", x)循环输出 → 末尾多空格 - 用
cout << x << " "→ 同样多空格 - 忽略
n == 1时只输出1
正确实现(C++):
#include <iostream> #include <vector> using namespace std; int main() { long long n; cin >> n; vector<long long> seq; seq.push_back(n); while (n != 1) { if (n % 2 == 0) { n /= 2; } else { n = 3 * n + 1; } seq.push_back(n); } // 关键:手动控制空格,避免末尾空格 for (size_t i = 0; i < seq.size(); ++i) { cout << seq[i]; if (i < seq.size() - 1) cout << " "; } cout << endl; return 0; }参数说明:
long long是必须的——当 $ n = 999999 $ 时,中间值会超过int上限($ 2^{31}-1 $)。vector存储序列而非边算边输,是为了确保顺序和空格可控。此处不用endl替代\n,因 CSES 测试脚本对换行符敏感(Windows 行尾会判 WA)。
2.3 本地测试:用官方test.sh脚本,不依赖任何网络
CSES 仓库根目录下自带test.sh,它是唯一被官方认可的本地验证方式。其原理极简:对每个*.in文件,执行你的程序重定向输入,捕获输出,与对应*.out比较。不要自己写diff命令——test.sh会自动处理空格、换行、大小写等细节:
# 编译你的代码(假设保存为 weird.cpp) g++ -std=c++17 -O2 weird.cpp -o weird # 进入题目目录,运行测试 cd problems/weird-algorithm/ ../test.sh ../weird预期输出:
Testing test case 1... OK Testing test case 2... OK ... Testing test case 10... OK All tests passed!逻辑说明:
test.sh会遍历../../tests/weird-algorithm/下所有*.in文件,执行../weird < 1.in > tmp.out,再用diff -wB tmp.out ../../tests/weird-algorithm/1.out比较(-wB忽略空格和空白行)。若失败,会显示FAILED并输出你的输出与期望输出的 diff。
3. 题目分类与进阶路径:按知识图谱拆解 300+ 题,避开「随机刷题」陷阱
CSES-Problem-Set 的题目不是按难度编号,而是按算法范式聚类,共 23 个目录(如sorting-and-searching/,graph-algorithms/,dynamic-programming/)。盲目从1001刷到1300会导致知识断层——比如你在tree-algorithms/里卡住,很可能是因为没先掌握binary-lifting/或euler-tour/的前置题。我按实际教学反馈,将 300+ 题划分为 5 层能力阶梯,并标注每层必做题(标 ★)和易踩坑点:
| 能力层 | 覆盖目录 | 核心能力 | 必做题(★) | 典型陷阱 |
|---|---|---|---|---|
| L1:输入输出与基础控制流 | introductory/,sorting-and-searching/ | cin/cout边界、二分查找模板、STL 正确用法 | weird-algorithm★,missing-number★,repititions★ | lower_bound返回迭代器而非下标;sort(v.begin(), v.end())忘写v.end() |
| L2:数据结构实现与应用 | ># 编译后立即添加执行权限 g++ -std=c++17 -O2 weird.cpp -o weird chmod +x weird # 或者一步到位(推荐) g++ -std=c++17 -O2 weird.cpp -o weird && chmod +x weird4.2 现象: |