逝者如斯,不舍昼夜

尘世中一个迷途小书童,读书太少,想得太多
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

《算法竞赛入门经典》第二章精选

Posted on 2015-08-14 17:29  SteveWang  阅读(522)  评论(0编辑  收藏  举报

 

例2-4 文件读写(freopen重定向)

 

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

  样例输入:2 8 3 5 1 7 3 6

  样例输出:1 8 4.375

#include<stdio.h>
#define INF 1000000000

int file_freopen()
{
    int x,min=INF,max=-INF,S=0,count=0;
    freopen("E:\\Code\\C\\算法竞赛入门经典\\Debug\\input.txt","r",stdin);
    freopen("E:\\Code\\C\\算法竞赛入门经典\\Debug\\output.txt","w",stdout);
    while(scanf("%d",&x)==1)
    {
        S+=x;
        if(x<min) min=x;
        if(x>max) max=x;
        count++;
    }
    printf("%d %d %.3lf\n",min,max,(double)S/count);

    return 0;
}

 

 

例2-4 文件读写(fopen)

 

#include<stdio.h>
#define INF 1000000000

int file_fopen()
{
    int x,min=INF,max=-INF,S=0,count=0;
    FILE *fin,*fout;
    fin = fopen("E:\\Code\\C\\算法竞赛入门经典\\Debug\\input.txt","rb");
    fout = fopen("E:\\Code\\C\\算法竞赛入门经典\\Debug\\output.txt","wb");
    while(fscanf(fin,"%d",&x)==1)
    {
        S+=x;
        if(x<min) min=x;
        if(x>max) max=x;
        count++;
    }
    fprintf(fout,"%d %d %.3lf\n",min,max,(double)S/count);
    fclose(stdin);
    fclose(stdout);

    return 0;
}

 

 

习题2-2 水仙花数(daffodil)

 

  题目:输出100 ~ 999中的所有水仙花数,若3位数ABC满足ABC = A3 + B3 + C3,则称其为水仙花数。例如153 = 13 + 53 + 33,所以153是水仙花数。
  分析:考查的是循环的用法。
  源码

#include<stdio.h>

int daffodil()
{
    int a,b,c,x;
    for(a=1;a<=9;a++)
    {
        for(b=0;b<=9;b++)
        {
            for(c=0;c<=9;c++)
            {
                x=a*100+b*10+c;
                if(x==a*a*a+b*b*b+c*c*c)    //ABC=A*A*A+B*B*B*C*C*C
                    printf("%d\n",x);
            }
        }
    }

    return 0;
}

 

  运行结果

  

 

 

习题2-4 倒三角形(triangle)

 

   题目:输入正整数n<=20,输出一个n层的倒三角形。例如n=5时输出如下:

  

  分析:考查的是循环的用法,注意空格和#于层数之间的关系。
  源码

#include<stdio.h>

int triangle()
{
    int n,i,j,k;                    //共n行
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        for(j=1;j<i;j++)            //第i行先打印i-1个空格
            printf(" ");
        for(k=1;k<=2*n-(2*i-1);k++)    //第i行再打印2n-(2i-1)个#
            printf("#");
        printf("\n");    
    }

    return 0;
}

 

 

习题2-8 子序列的和(subsequence)

 

  题目:输入两个正整数n<m<106,输出1/n2 + 1/(n+1)2 + …… + 1/m2,保留5位小数。例如n=2,m=4时答案是0.42361;n=65536,m=655360时答案为0.00001。注意:本题有陷阱。
  分析:本题陷阱在于n比较大时,n*n会溢出,所以 1/n2 应该用 1/n/n 而不是 1/(n*n)
  源码

#include<stdio.h>

int subsequence()
{
    int n,m,i;
    double sum=0.0;
    scanf("%d%d",&n,&m);
    for(i=n;i<=m;i++)
    {
        sum+= 1.0/i/i;    //防止i*i溢出
    }
    printf("%.5lf\n",sum); 

    return 0;
}

 

 

习题2-10 排列(permutation)

 

  题目:用1,2,3,……,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi = 1:2:3。输出所有解。提示:不必太动脑筋。
  分析:利用数组,sign[1]~sign[9]初始赋值为0,令sign[出现的数字] = 1,若sign[1] + sign[2] + …… +sign[9] == 9,则9个数字本次均出现一次。
  源码

#include<stdio.h>

int permutation()
{
    int abc, def, ghi, sign[10] = {0};    //数组sign的初始值为0,当1,2,3,……,9中某一数字出现就令对应下标的数组元素为1
    int i, sign_sum = 0;  
    for(abc = 100; abc < 333; abc++)    //abc一定小于333
    {  
        def = 2*abc;  
        ghi = 3*abc;  
        /*令 sign[在三位数的百位、十位、个位出现的数字] = 1*/  
        sign[abc/100] = sign[abc/10%10] = sign[abc%10] = 1;  
        sign[def/100] = sign[def/10%10] = sign[def%10] = 1;  
        sign[ghi/100] = sign[ghi/10%10] = sign[ghi%10] = 1;  
        for(i = 1; i <= 9; i++)        //将sign相加,若和为9则1~9全部数字都出现一次
            sign_sum += sign[i];  
        if(sign_sum == 9)  
            printf("%d\t%d\t%d\n",abc,def,ghi);  
        for(i = 1; i <= 9; i++)        //数组sign重新赋值为0  
            sign[i] = 0;  
        sign_sum=0;                    //sign_sum置0
    }  

    return 0;
}

 

  运行结果