This blog has been shut down permanently.

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  13 随笔 :: 0 文章 :: 25 评论 :: 0 Trackbacks

1.输入输出

ACM和TopCoder不同,TopCoder只用让参赛者写一个class,而ACM需要参赛者完成整个console程序.在TopCoder中,输入输出是通过parameter传递的,不用过多考虑,在ACM中,却需要自己编写.

(1).只有一组输入时,这种情况不用我说了,都会,但是通常也不会有这么水的题

(2).固定组数的输入,可以利用一个计数器和while语句完成,

01 #include <iostream>
02
03 int main(void){
04     int n;
05     scanf("%d", &n);
06     while (n--){
07         //...
08     }
09     //...
10     return 0;
11 }

(3).测试数据结尾有标志字符(例如最后一组输入后给一个0),这个只用加一个if语句判断读入的数据是什么,是结束标志跳出就ok了.也不多说了

(4).题目没有告诉你有多少组数据,这个通常是最令新手疑惑的,这种情况,一般用文件结束标志EOF判断

01 #include <iostream>
02
03 int main(void){
04     int n;
05     while (scanf("%d", &n) != EOF){
06     //...
07     }
08     //...
09     return 0;
10 }

其实这里也可以用c++的cin输入流判断,例如

01 #include <iostream>
02
03 using namespace std;
04
05 int main(void){
06     int n;
07     while (cin>>n){
08     //...
09     }
10     //...
11     return 0;
12 }

但是这样不是特别好,为什么?下面会说.

对于输出,最好采用的接收一组数据,处理一组数据,把结果保存在一个缓冲数组中,待所有输入结束后,再一起输出,而不是待接收完所有输入后,再处理,再输出,这样会消耗更多的memory,而且会更慢.

2.关于效率

第一,上面的所有例子,均采用的c标准I/O,为什么不用c++的cin,cout呢?是有原因的,经实践,在大规模输入输出下,cin,cout效率远远低于scanf()和printf(),原因据我估计应该是以为scanf(),printf()是汇编写的(这点可以从这两个函数均可以接受任意多组parameter(s)看出,c/c++函数是不具备这样的性质的),而cin,cout均是直接c/c++写的流操作,本来c/c++就比汇编慢,还引入流,所以自然比scanf(),printf()慢了.因此,在输入输出数据量很小的情况下,出于方便的原因,可以采用cin,cout,而在输入输出数据量比较大的情况下用scanf(),printf()比较保险,避免超时.

第二.ACM中,除了c/c++,一般还支持java等语言,但是由于java是解释执行的,效率十分低下,为此,一般的JudgeOnline都把java的time limit设置为题目给定值(也就是c/c++的time limit)的三倍,而且给每一组输入再额外提供150ms.即使是这样,java遇上复杂或者高精度计算的题目,还是很容易超时,因为效率有时候还远远未到c/c++的1/3.因此,一般来说,除了个别java极其有利的情况(例如字符串处理),不建议使用java.

3.关于所得结果的解释

下面是一般JudgeOnline系统所有可能产生的结果,如果对返回的结果不明,看看解释吧

Waiting: Your program is being judged or waiting to be judged.

Accepted (AC): Congratulations! Your program has produced the correct output!

Presentation Error (PE): Your program's output format is not exactly the same as required by the problem, although the output is correct. This usually means the existence of omitted or extra blank characters (white spaces, tab characters and/or new line characters) between any two non-blank characters, and/or blank lines (a line consisting of only blank characters) between any two non-blank lines. Trailing blank characters at the end of each line and trailing blank lines at the of output are not considered format errors. Check the output for spaces, blank lines, etc. against the problem's output specification.

Wrong Answer (WA): Your program does not produce the correct output. Special judge programs will possibly return Wrong Answer in place of Presentation Error for simplicity and robustness.

Runtime Error (RE): Your program has failed during the execution. Possible causes include illegal file access, stack overflow, out of range in pointer reference, floating point exception, division by zero and many others. Programs that stay not responding for a long time (not consuming CPU cycles) may also be considered to have encountered runtime errors.

Time Limit Exceed (TLE): The total time your program has run for has exceeded the limit.

Each problem has two time limits - TOTAL TIME LIMIT and CASE TIME LIMIT. The former is the total time allowed for your program to deal with all input files. And the latter is the total time allowed for your program to deal with a single input file. Exceeding either one will lead to Time Limit Exceed. If you get Time Limit Exceed but find that your program has run for less time than is limited, your program must have exceeded that CASE TIME LIMIT.

Problems without a special demand on the time limit for a single input file will have its case time limit is trivially set as the same as its total time limit and the phrase "Case Time Limit" will not show up under the problem title.

Memory Limit Exceed (MLE): The maximum amount of memory that your program has used has exceeded the limit.

Output Limit Exceed (OLE): Your program has produced too much output. Currently the limit is twice the size of the file containing the expected output. The most common cause of this result is that your programs falls into an infinite loop containing some output operations.

Compile Error (CE): The compiler fails to compile your program. Warning messages are not considered errors. Click on the judge's reply to see the warning and error messages produced by the compiler.

No such problem: Either you have submitted with a non-existent problem id or the problem is currently unavailable (probably reserved for upcoming contests).

System Error: The judge cannot run your program. One example is that your program requires much more memory than hardware limitation.

Validate Error: The special judge program fails in checking your output, which means it may contain some bugs. If you get this result, please contact the administrator. (Of course, this also means your output is probably wrong).

posted on 2009-11-11 00:43 iZ 阅读(1828) 评论(11)  编辑 收藏 引用

评论

# re: [转载]ACM技巧——for amateur only 2009-11-11 03:17 OwnWaterloo
"经实践,在大规模输入输出下,cin,cout效率远远低于scanf()和printf()"
远远低于? 太夸张了……
野蛮人拿到打火机可能也会抱怨"还不如我的木头"。

看看这个:
http://acm.pku.edu.cn/JudgeOnline/problemstatus?problem_id=2602

第1个uther的,就是用C++ iostream做的。

  回复  更多评论
  

# re: [转载]ACM技巧——for amateur only 2009-11-11 19:16 iSsay
@OwnWaterloo
uther只是预处理包含了流处理的定义,但是他有没有调用cin/cout那我就不知道了。  回复  更多评论
  

# re: [转载]ACM技巧——for amateur only 2009-11-11 19:19 iSsay
@OwnWaterloo
换句话说,说不定他预先包含的是iostream,里面用的都是汇编代码呢
:-)  回复  更多评论
  

# re: [转载]ACM技巧——for amateur only 2009-11-11 20:30 OwnWaterloo
@iSsay
少扯了,uther是我临时注册的马甲。

  回复  更多评论
  

# re: [转载]ACM技巧——for amateur only 2009-11-11 21:12 iSsay
@OwnWaterloo
我有眼不识泰山,大牛啊,能看看你的代码吗?  回复  更多评论
  

# re: [转载]ACM技巧——for amateur only 2009-11-11 21:26 OwnWaterloo
@iSsay
就事论事而已,我不是大牛,pku上就没过几道题。
代码里面有很多速度测试的代码,所以很长。

其实是用istream::read 一次读完所有输入到buf。
将buf[0],buf[2],buf[4], ... 看作a
将buf[1],buf[3],buf[5], ... 看作b
然后高精度加高精度。
加法时没有没有转换到0-9 直接用'0'-'9'计算,输出时也省去了另一次转换,直接输出一个字符串。

  回复  更多评论
  

# re: [转载]ACM技巧——for amateur only 2009-11-11 23:02 iSsay
你有没有试过,用测速代码测试iostream,和标准IO的效率?  回复  更多评论
  

# re: [转载]ACM技巧——for amateur only 2009-11-11 23:05 OwnWaterloo
@iSsay
标准IO?cin,cout,cerr,clog不就是标准IO么?

你指的是formatted io?

  回复  更多评论
  

# re: [转载]ACM技巧——for amateur only 2009-11-12 00:08 OwnWaterloo
@iSsay
这个嘛,你去测吧,嘿嘿。


做2602的背景是这样的:chinaunix上有人说poj上有题目建议使用scanf/printf,否则做不出来。
然后我就去试了试。 先随便在网上扒了一份代码,TLE……
干脆自己写,用g++提交,结果就过了,换c++提交,第2次就跳到no1去了。
不过oj上的时间测不准,精度太低。其他人多提交几次可能也会冲到no1去。


iostream的格式化是静态分派的,printf/scanf是动态分派。
在格式化上,iostream的机制理论上的效率是会高而不是低。

iostream输在格式化后的其他事情上去了。iostream下还有一层client可知的streambuf层次。

iostream多这一个层次,就将"格式化"与"缓冲"工作分开了。
你可以复用iostream的格式化功能,但给它一个不同于file的目的地,比如socket、memory、null —— 只要传递给它相应的streambuf就行。

对于memory作为目的地,stl提供了stringbuf。并有相应的stringstream在iostream上增加一些接口,使得client不用直接操纵stringbuf。
C标准库相应有sprintf,sscanf。但要这么看,sprintf不能扩容。
类似的还有在我最开始接触vector的时候,也觉得它慢。因为我拿vector和固定大小数组比较。但当我不做oj,数组大小不方便提前计算出时,怎么办?
而且,stl其实还有strstream……

以socket作目的地? printf/scanf怎么搞?
自己实现printf/scanf吗? 你觉得这容易吗?
如果不自己实现printf/scanf,那就只能利用缓存。
拿这种情况和iostream + socketbuf比较,那才公平。

iostream还有很多乱七八糟的功能,locale,expcetion,callback,fillchar……

总之,在一个只处理build-in类型,数组/缓冲大小可以提前计算并按最大值提供,不需要按需提供/扩展,不处理多语言的情况下 —— OJ的情况下 ——确实利用不了iostream,vector等提供的功能。
但OJ做多了,就反过来说它们的不是,就很扯蛋了。
说实话,OJ的代码普遍是上不得台面的,大家自己心里清楚。
根本就没有一点点软件工程的美感在里面。可复用吗?不能,都是一次性筷子,完全是为了AC而已。

在实际开发中,没有这么多美好的前提条件。

即使iostream功能比printf/scanf多得多,如果iostream的格式化比printf/scanf有数量级的差异,没得说,那肯定是iostream实现得太烂……
同样的是格式化和读写文件操作,多一个间接层次就导致效率数量级的下降?那不是写得烂能是什么呢?找个好点的吧。
还有用VC6的OJ(非POJ),你能拿它怎么办呢?

  回复  更多评论
  

# re: [转载]ACM技巧——for amateur only 2009-11-12 14:38 OwnWaterloo
好像说偏题了……

chinaunix上讨论时,他并没有说是哪一题,只说有题目提示说要用scanf/printf。他自己也记不清楚是哪一题了。
2602是我自己找出来的,觉得这题比较变态。

如果楼主在做其他题目时,发现题目下面有提示说使用scanf/printf的话,还请通知我一下,谢谢~_~
  回复  更多评论
  

# re: [转载]ACM技巧——for amateur only 2009-11-15 16:25 iSsay
@OwnWaterloo
POJ2602上面那道题,可能没有体现出printf的优点吧。如果加上格式控制就不一样了。
那个hint估计也就是这个意思,就有点像入门题,先给你一个提示,让你以后做题的时候考虑到printf。。
  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理