初学acmer--读《算法竞赛入门经典》笔记(三)p27-34

来源:互联网 发布:tomcat80端口被占用 编辑:程序博客网 时间:2024/04/29 19:27

题目:数据统计       (p27-32)

输入一些整数,求出它们的最小值、最大值和平均值(保留三位小数),输入保证这些数都是不超过1000的整数

          样例输入

2 8 3 5 1 7 3 6

          样例输出

1 8 4.375

先给代码(有bug)

#include<stdio.h>int main() {int x,n=0,min,max,s=0;while(scanf("%d",&x)==1){s+=x;if(x<min)min=x;if(x>max)max=x;n++;}printf("%d %d %.3f\n",min,max,(double)s/n);return 0;}

1.scanf()函数返回成功输入的变量个数,当输入结束时,scanf函数无法读取变量,将返回零

2.在Windows下,输入完毕后先按Enter键,再按Ctrl+Z键,最后按Enter键即可结束输入

  在Linux下,输入完毕后按Ctrl+D键即可结束输入

3.但是输出结果却是不确定的,通过输出中间结果的方法,很容易发现变量max,min一开始未初始化

书上解决方法:可以用一个很小的值来初始化max;用一个很大的值来初始化min

 本题中可以使INF=1000;max=-INF;min=INF;

自己想法:min,max都用第一个读取的数来初始化

代码如下:

#include<stdio.h>int main() {int x,n=0,min,max,s=0;while(scanf("%d",&x)==1){s+=x;min=x;max=x;n++;                                     //min,max都用第一个读取的数来初始化while(scanf("%d",&x)==1){s+=x;if(x<min)min=x;if(x>max)max=x;n++;}break;}printf("%d %d %.3f\n",min,max,(double)s/n);return 0;}
4.本题是手动输入,略显麻烦,可以采取文件输入方式

使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入两条语句:

freopen("input.txt","r",stdin);

freopen("output.txt","w",stdout);

ps:在算法竞赛中,首先要弄清是标准输入输出,还是文件输入输出?如果是文件输入输出,是否禁止用重定向方式访问文件

另外也要严格遵守文件名规定,包括程序文件名和输入输出文件名。不要弄错大小写,不要拼错文件名,不要使用绝对路径或相对路径
5.当然,即使比赛要求是标准输入输出,也可以使用文件输入输出,可以避免繁琐的手动输入输出,但是最后提交时可以用条件编译指令将重定向语句删掉

代码如下:

#include<stdio.h>#define LOCAL                                    //在标准输入输出比赛中,最后要记得注释掉这一行#define INF 1000 int main() {#ifdef LOCALfreopen("input.txt","r",stdin);        freopen("output.txt","w",stdout);         #endifint x,n=0,min=INF,max=-INF,s=0;while(scanf("%d",&x)==1){s+=x;if(x<min)min=x;if(x>max)max=x;n++;}printf("%d %d %.3f\n",min,max,(double)s/n);return 0;}
6.如果比赛要求用文件输入输出,但禁止用重定向的方式,代码如下:

#include<stdio.h>#define INF 1000 int main() {FILE *fin,*fout;fin=fopen("data.in","rb");fout=fopen("data.out","wb");int x,n=0,min=INF,max=-INF,s=0;while(fscanf(fin,"%d",&x)==1){s+=x;if(x<min)min=x;if(x>max)max=x;n++;}fprintf(fout,"%d %d %.3f\n",min,max,(double)s/n);fclose(fin);fclose(fout);return 0;}
ps:重定向和fopen两种方法各有优劣

重定向简单自然,但是不能同时读写文件和标准输入输出

fopen的写法较为繁琐,但是灵活性比较大,例如可以反复打开并读写文件,也可以通过赋值“fin=stdin;fout=stout”并删掉调用fopen和fclose语句来改成标准输入输出
题目:数据统计||      (p32-34)

输入一些整数,求出它们的最小值、最大值和平均值(保留三位小数),输入保证这些数都是不超过1000的整数

输入包含多组数据,每组数据第一行是整数个数n,第二行是n个整数。n=0为输入结束标志,程序应当忽略这组数据。相邻两组数据之间应输出一个空行

         样例输入

8

2 8 3 5 1 7 3 6

4

-4 6 10 0

0

       样例输出

Case 1:1 8 4.375

Case 2:-4 10 3.000

老规矩,先贴代码(有bug):

#include<stdio.h>#define INF 1000 int main() {int x,n=0,min=INF,max=-INF,s=0,kase=0;while(scanf("%d",&n)==1&&n){    int s=0;    for(int i=0;i<n;i++)    {    scanf("%d",&x);    s+=x;if(x<min)min=x;     if(x>max)    max=x;    }if(kase)  printf("\n");                                        //为了符合题目“相邻两组数据之间应输出一个空行”这一要求printf("Case %d: %d %d %.3f\n",++kase,min,max,(double)s/n);}return 0;}
1.程序之所以仍然判断scanf的返回值,是为了提高代码的鲁棒性,即为了防止比赛数据有瑕疵
2.kase的使用是为了符合题目“相邻两组数据之间应输出一个空行”这一要求

3.当在样例输入的最后增加第三组数据:1 0

输出为Case 3:-4 10 0.000

很明显,这是上一组的数据结果

由此可见:在多数据的题目中,一个常见错误是:在计算完上一组数据后,某些重复使用的变量没有重置,从而影响到下一组数据的结果


阅读全文
0 0