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

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

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

          样例输入

2 8 3 5 1 7 3 6

          样例输出

1 8 4.375

先给代码(有bug)

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

#include
#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(xmax)
		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
#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;imax)
	    	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

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

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


你可能感兴趣的:(acm)