清华大学计算机系 数据结构教学团队tsinghuax+30240184.1x+1t2016+typ… ·...
TRANSCRIPT
数
据
结
构
编
程
作
业
说
明
清华大学计算机系
数据结构教学团队
2016.02
目录
1 课程与作业 ................................................................. 1
1.1 作业概述 ............................................................. 1
1.2 作业提交 ............................................................. 1
1.3 无效的提交 ........................................................... 1
1.4 补交 ................................................................. 2
2 评分方式................................................................... 2
2.1 诚信守则 ............................................................. 2
2.2 黑盒评测 ............................................................. 2
2.3 白盒评测 ............................................................. 2
3 课程要求................................................................... 3
3.1 MOOC课堂(xuetangX, edX) ........................................... 3
3.2 全校选修课(秋季) ................................................... 3
3.3 全校选修课(SPOC春季) .............................................. 3
3.4 计算机系专业课 ....................................................... 4
3.5 其它课堂 ............................................................. 4
附:FAQ...................................................................... 4
附:OJ分档评测的图片说明 .................................................... 6
附:新增 Java支持 ............................................................ 7
附:OJ使用技巧 .............................................................. 8
附:输入输出技巧 ............................................................. 8
附:一些常见编程错误 ........................................................ 10
附:Visual Studio msvc与 GNU gcc的差异 ..................................... 11
1
1 课程与作业
1.1 作业概述
编程作业在线提交,网址 http://dsa.cs.tsinghua.edu.cn/oj/。
有些课程是公开课程(如 MOOC等),在 Course->Select public courses 里直接选课。
有些课程是私有课程,需要使用教师发放的邀请码选课,或直接由教师加进课堂。
进入一个课堂,有若干次编程作业(简称 PA),并在左边显示 PA 截止时间。PA 标题的
背景,绿色表示尚未截止,红色表示即将在一周内截止,灰色表示已经截止。
每个 PA有若干道题目,各题目在本次 PA中占的比重在题目标题的后面。
题目通常分为标题、描述、输入、输出、样例、限制、提示等部分。
如无特殊说明,所有题目统一使用标准输入和标准输出。
在“限制”部分,通常都指定了输入的取值范围,你的程序不必考虑范围之外的情况。
在“限制”部分,有的题目限制了你能使用的方法。
程序输出应与标准答案一致,请留意多余的空格、制表符、回车和换行。行末空格和文
末换行一般不会影响评分。
每题得分由黑盒测试和白盒测试组成,成绩比例详见“课程要求”节。
提醒:应对算法的时间和空间复杂度做充分和准确的估计,正确但低效的程序无法获得
高分,甚至可能无法得分。
1.2 作业提交
在截止时间前,提交代码至 OJ并“标记为最终版本”(Mark it as final version);
截止时间前可以多次标记,以最后标记的为准;通过其它渠道(电子邮件、网络学堂等)提
交的无效。
每道题需要在 OJ 上签署 Honor Code。有的课程不需要 Honor Code,详见“课程要求”
节。
每道题需要在 OJ 上提交一份解题报告(Report)。有的课程不需要 Report,详见“课
程要求”节。
代码如果含有多个文件,可以将所有代码置于顶层目录直接打包(zip、tar、gz 等格
式)提交。
每次提交的代码文件不超过 200KB。
1.3 无效的提交
无效的提交记 0分,包括(但不限于)以下方面:
a) 未在作业截止时间前标记最终版本。
b) 标记的最终版本在 OJ上无法通过编译。
c) 需要签署 Honor Code但未签署。
2
d) 未在题目“限制”部分规定的范围内选用数据结构和算法。(题目“提示”部分只
是提供了一些方法,不具有约束力)
注:如果需要提交 Report但未提交,那么只会导致本题白盒成绩计 0 分,不会导致整
题无效。
1.4 补交
补交作业会影响整个课堂的代码查重和白盒评测,因此原则上不接受补交。
向老师或助教说明情况后,如果接受补交,该题分数按每 12 小时折扣 15%计算;72小
时后将折扣到 0%,即使补交也无法获得分数。
2 评分方式
2.1 诚信守则
若标记的最终版本出现代码雷同,则在 Honor Code中未予声明者题分记-100分,有声
明者题分酌情折扣。
若查阅资料参考了代码,但在 Honor Code中未予声明,则题分酌情折扣。
过度参考资料,在一定程度上降低了作业难度,可能影响起评分。
若标记的最终版本出现代码雷同,但没有签署 Honor Code,那么按无效的提交计算,
记 0分而不会记负分,代码雷同的另一方也不会因此受到影响。
2.2 黑盒评测
每题参与黑盒测试的代码版本,以作业截止前最后一次标记的为准。
评测分为“五成测”“九成测”和“全集测”。
“五成测”:测前 50 %的测试点。
“九成测”:测前 90 %的测试点。
“全集测”:测所有测试点。
作业截止时,统一对所有学生的最终版本进行“全集测”,以这次测试成绩作为本题的
黑盒测试成绩。
作业截止后,可以自由“全集测”。有三天申诉期,如果发现“全集测”成绩与黑盒测
试成绩有较大差异,请提出申诉。
参考“附:OJ分档评测的图片说明”。
2.3 白盒评测
先考察解题报告(Report),然后考察代码风格、模块划分、注释清晰度等。若没有提
交 Report,则该题白盒测试记 0分。
3
解题报告请尽量使用纯文本,内容包括(但不限于):
1. 所使用数据结构与算法的构思、原理和实现要点。
2. 完成过程中遇到的问题,排除问题的主要过程、使用的方法和技巧,以及参考资料。
3. 时间和空间复杂度的估算。
4. (可选)介绍理论分析与实测效果的吻合程度,不吻合时进一步解释原因。
5. (可选)所用方法的特别、新颖或创新之处。
使用全局变量,或使用分装性差的数据结构往往会影响白盒得分。
3 课程要求
3.1 MOOC 课堂(xuetangX, edX)
不需要签署 Honor Code,不需要提交 Report。
黑盒评测总是使用全集测。
黑盒评测成绩占 100%,不进行白盒评测。
不进行代码查重。
允许使用 C/C++/JAVA 语言。使用 C++时禁止使用 STL。
从 MOOC 晋级到 THU/CST 课堂的学生,在 THU/CST 课堂上也不需要签署 Honor Code 和
提交 Report,黑盒评测成绩占 100%,不进行代码查重。
3.2 全校选修课(秋季)
需要签署 Honor Code,并需要提交 Report。
作业截止前使用五成测,每人每题还有 5次九成测的机会。
黑盒测试成绩视情况占 60%~80%,白盒测试成绩占剩余的分数。
进行代码查重。
只允许使用 C/C++语言。禁止使用 STL。
3.3 全校选修课(SPOC 春季)
需要签署 Honor Code,并需要提交 Report。
作业截止前使用五成测,每人每题还有 5次九成测的机会。
黑盒测试成绩视情况占 60%~80%,白盒测试成绩占剩余的分数。
进行代码查重。
只允许使用 C/C++语言。禁止使用 STL。
每次作业只取得分最高的 N题,N在学期初确定。
4
3.4 计算机系专业课
需要签署 Honor Code,并需要提交 Report。
作业截止前使用五成测,每人每题还有 5次九成测的机会。
黑盒测试成绩视情况占 60%~80%,白盒测试成绩占剩余的分数。
进行代码查重。
只允许使用 C/C++语言。禁止使用 STL。
3.5 其它课堂
其它课堂由教师确定评分方案。
下表简要对比以上四个课堂的要求。
MOOC THU THU(SPOC) CST
Honor Code 不需要 需要 需要 需要
Report 不需要 需要 需要 需要
黑盒测试点 全集测 五成测/九成测 五成测/九成测 五成测/九成测
黑盒成绩比重 100% 60%~80% 60%~80% 60%~80%
白盒成绩比重 0% 20%~40% 20%~40% 20%~40%
代码查重 无 有 有 有
JAVA语言 接受 禁用 禁用 禁用
STL 禁用 禁用 禁用 禁用
附:FAQ
1. 杂项
a) 助教的联系方式?
在 Piazza讨论区的公告中有助教的联系方式。本课程主要使用 Piazza讨论区讨论、解
答问题。
https://piazza.com
b) 课程讲义在哪下载?
讲义统一在 MOOC 学堂在线的数据结构课堂发布。
c) 如何提问,并更加高效地得到有帮助的解答?
描述问题时请不要过于概括,比如这样两个问题:
“我本地运行正确怎么在 OJ上就错了?”
“我本地运行正确,为什么 OJ上编译错误,并提示 main should return int?”
显然,后者更能得到有帮助的回答。
5
d) 请问总评成绩的额外加分是什么意思?
请参见讲义“00.Syllabus”一节中的相关说明。
2. OJ 使用说明
a) OJ 上需要提交哪些文件?
只需要提交源代码文件(*.cpp/*.c/*.h)和 readme.txt,其余文件尽量不要一同打包。
b) OJ 上的编译环境与本地有何不同,需要注意哪些问题?
OJ 使用的是 Linux系统,GCC 4.9.2编译器,不支持 C++11。它与 Visual Studio中的
MSVC 编译器有一些微小的区别,例如:main 函数的返回值必须为 int,默认不会包含
任何头文件等等。一般认为 GCC编译器是更加符合 C / C++标准的,所以如果遇到了本
地编译成功 OJ编译失败的例子,请根据提示进一步修改源程序。
主要区别在“附:Visual Studio msvc与 GNU gcc的差异”中列出。
c) OJ 上是否禁止使用某些库?
是的,在 OJ上移除了某些头文件,例如 vector、algorithm。原则上,只要你的作业能
够通过编译,且不违反课程要求和题目要求,就没有任何问题。不过不包括手动把这些
头文件与你的作业其他代码一同打包提交上来:)
d) 输入输出应该采用哪些函数?
请使用 scanf 和 printf 来代替 cin 和 cout,某些情况下后者效率远远远远低于前者。
更高效的读入是用 fread,然后手动解析文本。
e) Runtime Error是怎么回事?
Runtime Error是指程序在运行过程中出现了问题,通常是内存访问的问题,比如数组
下标越界。一般这些问题在小规模测试的时候不会发现,而在 OJ 上大规模数据测试时
候就容易暴露出来,所以请自行构造一些数据来调试程序。此外,需要注意的是,main
函数必须以 return 0;结束,如果返回值非 0,也会被认为是 Runtime Error。如果保
证 返 回 值 为 0 并 且 希 望 知 道 OJ 返 回 错 误 代 码 的 含 义 , 可 以 参 考
http://dsa.cs.tsinghua.edu.cn/oj/static/unix_signal.html。常见的是 8除 0错和
11 内存访问错误。
f) 我的运行结果是 Exceed time limit,时间 2200ms,是不是只要再做一些常数级优化就
不会超时了?
当超过题目规定的时限,OJ 会杀死进程。显示用时 2200ms,说明程序运行时间超过时
限(2s),并不说明程序只花 2200ms就能运行完。因此,不是把程序运行速度优化 200ms
就能解决的。
3. 作业说明
a) 必须采用题目中【提示】所指出的方法吗?
不是的,题目中的【提示】只是一种可行思路,不排除有更好的思路,可以任意选择方
法。但是如果题目正文和题目的【限制】中对方法有限制,那么必须遵守。
b) 每个作业只能标记一次 Final Version吗?
6
Deadline前可以多次 mark final version,评测时以最后一次 mark的为准。
c) 程序调试了很久没有调通,可以使用助教来进行调试吗?
由于调试工作量实在太大,所以助教不会来帮助大家进行调试:)比较建议大家在同学中
寻找一些伙伴来互相帮助调试,这样双方都会有明显的进步,助教自己的程序就是这样
调试的。
d) 题面上的“输入样例”就是第一个测试点吗?
不一定,输入样例与测试点没有直接联系。
e) 教材上的示例代码可以直接在作业中使用吗?
1. 支持借鉴、学习教材中的代码,完善自己作业程序的效率;
2. 如果直接使用教材中的代码,需要进行声明;
3. 原则上,并不鼓励使用教材和课件中的代码,鼓励同学们自己实现、完善相应的数
据结构;
4. 教材中的代码,更多的是一种原理的示范,并不保证正确性,如果因此出现 Bug,
请同学们自负后果。
f) 如果作业抄袭后果如何?
这会给被抄袭同学带来极大的困扰,因为会导致记-100分,太惨了:)
提前说明的是本课程对作业雷同的判定比较严格,所以请大家独立完成作业。
需要强调的是,在签署的 Honor Code 中,你已承诺“我未曾也不会向同一课程(包括
此后各届)的同学复制或公开我这份程序的代码,我有义务妥善保管好它们”。
附:OJ 分档评测的图片说明
作业截止前,有两个测试按钮。“50% Judge”进行“五成测”,不限限制。右边的小按
钮上的数字是“九成测”剩余机会数。初始状态下,每人每题有 5次“九成测”的机会。
使用“九成测”机会时,提交页面会显示一行警告。
7
你还可以为每次提交做批注,这样,批注会显示在测试结果的右边,以便你在众多提
交中分辨你的每次提交。
显示的分数是通过的测试点占所有测试点的比例,而不是通过测试点占参与测试的测
试点的比例。因此,“五成测”最高 50分,“九成测”最高 90分。
作业截止后,可以进行“全集测”,次数不限。你有申诉期,详见作业说明“黑盒测
试”部分。
附:新增 Java 支持
OJ 现已支持提交 Java源代码,需要提交一个压缩包:
1. 主类名是 Main
2. 使用标准输入、标准输出
3. 需打包提交,即使只是单文件
OJ 的打包规则:所有文件置于顶层目录打包,即点开压缩包就能看到 Main.java,而不
8
是点开压缩包后再点开一层目录才能看到 Main.java。
对应于“Tutorial”第一题“0.加法(Add)”,需要提交的打包文件可在这里下载:
http://www.xuetangx.com/asset-
v1:TsinghuaX+30240184+2015_T2+type@asset+block/JavaExample.zip
附:OJ 使用技巧
1. OJ 使用手册 http://dsa.cs.tsinghua.edu.cn/oj/guide.shtml
视 频 教 程 https://d2f1egay8yehza.cloudfront.net/tsg-ds/TSGDATAST114-
V052400_DTH.mp4
2. 几种主要的读入数据方法,大多数情况下性能是 fread > getchar > scanf > cin的
顺序。
3. OJ 上的编译器采用的是 gcc(g++),对于 Linux 和 Mac用户可以无缝衔接,而如果使用
Windows的同学希望能够在本地编译与OJ编译之间较快衔接的话,可以考虑使用MinGW。
4. Runtime Error的 exit code同样反映了某种信息,可以查阅相关资料了解 RE各个 exit
code的意义。参考 http://dsa.cs.tsinghua.edu.cn/oj/static/unix_signal.html。
5. 评测所依赖的输出流是 stdout,而使用 stderr 的输出不会被纳入最终评测——但如果
你使用 stderr进行调试却没有在提交中移除,这将显著地拖累你程序的性能。
6. 常用的调试工具包括 gdb、MSVC debugger、室友、小黄鸭。
7. 如果不确定某一特性是否为 OJ所支持,不妨动手试一试。
附:输入输出技巧
1. 判断输入结束
有些编程作业题并未指明测试数据的组数,此时需要自己判断输入结束。其实,根
据题意正确处理输入数据也是同学们在这门课中需要练习的编程能力之一。
处理输入的方法很简单,使用 C++风格的 cin,可以这样写
string a, b; char c;
while (cin >> a >> b >> c)
{ /* blablabla */ }
如果使用 C风格的 scanf()函数,则可根据其返回值做出判断,具体地可以这样写:
while (scanf("%s\n%s\n%c\n\n", &a, &b, &c) != EOF)
{ /* blablabla */ }
这样当格式输入流读到文件末尾时会返回 EOF,于是 while退出。
2. 过滤空白字符
有些题目是这样的输入格式:
E 6
M
9
E 2
M
即字母、数字混输。如果用 getchar 或 scanf 的%c 参数,会受到行末空白符(比
如空格、换行等)的困扰。cin到字符串、scanf的%s参数都会自动过滤空白符。使用
标准库的功能来过滤空白符,会使程序逻辑更清晰。示例代码:
char buf[8];
int x;
while (scanf("%s", buf) != EOF) {
switch (buf[0]) {
case 'E':
scanf("%d", &x);
/* balabala */
}
}
3. I/O缓存加速
使用 cstdio 中的 setvbuf函数,设置一个较大的 I/O 缓冲区,有时有很好的加速
效果。用法示例:
setvbuf(stdin, new char[1 << 20], _IOFBF, 1 << 20);
setvbuf(stdout, new char[1 << 20], _IOFBF, 1 << 20);
注意:一、必须在所有 I/O操作前调用这个函数,不能在已读入一些数据后再设置
缓存;二、如果设置了 I/O缓存,控制台输入输出可能失效。
4. 重定向
为便于反复测试及再现运行过程,可采用输出、输入重定向的方法。
你只需事先将输入数据存成文件,运行时系统会自动从中获取输入。其效果完全等
同于你从(作为默认输入流的)键盘逐项输入。
类似地,你也可以指定另一文件,并使运行的结果自动存入其中。其效果完全等同
于从(作为默认输出流的)屏幕截取输出结果。
重定向的好处很多:可以避免手工输入的出错,忠实可靠地重复测试;可以实现大
规模数据的输入;可以完整精确地记录程序的输出,以便事后的对比分析;可以省去默
认输入、输出流占用的大量时间,更加准确地测量程序的执行效率。
a) 方法一:修改源文件,指定重定向的输入、输出文件
例如,若希望从文件 input.txt 中获取输入,将输出保存到文件 output.txt
中,则可在主程序开头增加如下语句:
#ifndef _OJ_
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
注意:如果用 c++风格的 cin/cout 的话,还要在前面引用头文件的部分加入
#include <cstdio>。
OJ在编译程序的时候会提供一个_OJ_的符号,所以上面这段语句会在 OJ运行
的时候被跳过。
10
b) 方法二:在 IDE中通过设置命令行,重定向输入、输出文件
以 Visual Studio为例,可打开对应工程的“属性页”,在“配置属性”下的
“调试”页,设置“命令行参数”。
输入参数不多时,可直接键入。例如 ADD一题,键入“100 200”即可。若其
中包含特殊字符,则需以'^'引导,或者使用一对半角括号消除歧义。
若输入参数多,且不止一行,则可将其存成一个文件。比如,可在“命令行参
数”中键入:
< D:\test\input.txt
(注意起始字符"<"不能省略)
为将程序的输出保存至指定文件,可在“命令行参数”中继续键入:
> D:\result\output.txt
(同样地,起始字符"<"也不能省略)
若不希望覆盖文件原有的内容,只需用">>"替换以上的">",即可将每次运行
的输出追加至 D:\result\output.txt。
输入、输出的重定向可同时采用并生效。比如可在“命令行参数”中键入:
< D:\test\input.txt >> D:\result\output.txt
重定向文件的具体路径与文件名可自行选择,但若包含空格,则需使用一对半
角引号消除歧义,比如:
< "D:\my test\input.txt" >> "D:\my result\output.txt"
5. 帮助资料
关于输入输出的进一步问题,可以自己查阅相关手册或资料。
也可参考标准手册,以上输入输出方法都是 C/C++标准输入输出,在 manual 中都
有详细介绍。
cin:http://www.cplusplus.com/reference/iostream/cin/
scanf:http://linux.die.net/man/3/printf
对比:https://www.byvoid.com/blog/fast-readfile/
附:一些常见编程错误
1. swtich里忘记加 break,导致多个 case后的语句都被执行。
2. int *v = new int[n]误写成 int *v = new int(n)。前者申请了 n个 int 的空间;而
后者只申请了一个 int的空间,并初始化为 n。
3. 在函数里开了很大的数组,导致运行时栈溢出。错误示例:
int main() {
int v[1000000];
return 0;
}
可以改成:
int main() {
int *v = new int[1000000];
11
return 0;
}
4. 计算溢出示例:
int a = 1000000, b = 1000000;
long long int c = a * b;
程序会先在 int范围内计算 a * b,最后把溢出后的结果赋值给 c。正确写法是 c
= (long long)a * (long long)b。
附:Visual Studio msvc 与 GNU gcc 的差异
1. msvc可能会自动 include一些头文件,gcc编译提示函数找不到。
2. 使用 scanf等函数会警告 not safe(warning 4996),推荐使用 scanf_s,但是这个不
属于 C/C++标准,gcc没有。
3. gcc 也没有 itoa(数字转换为字符串的函数)。
4. gcc 上,模板类继承模板类,two phase name lookup,调用父类函数会提示找不到,
需要用 this->调用。
5. gcc 禁止 void main。main函数要 return 0,return非零值 OJ会认为是 runtime
error的 exitcode。
6. Windows和 Linux 上换行符有"\r\n"跟"\n"的差别,你的程序最好有一定鲁棒性,能处
理两种情况。