zoukankan      html  css  js  c++  java
  • 算法竞赛入门经典——第3章答案

    习题3-1 分数统计(stat)

    输入一些学生的分数,哪个分数出现的次数最多?如果有多个并列,从小到大输出。

    任务1:分数均不超过100的非负整数

    任务2:分数均不超过100的非负实数,但最多保留两位小数。

    这个类似单词统计词频,按字典序输出频率最高的那些。

     

    【思路】

    pic

    任务1和任务2差不多,换成double类型即可;现在以任务1为例解答——

    一种思路是从第二个读入的数字开始,从已有的集合(数组)中寻找,若重复则该元素的频率变量自增;否则添加新元素;

    最后根据频率变量排序,然后截取频率最高的那段(多个或者1个),再对该段按分数变量排序,最后输出这段数组的分数;

    代码:

    #include<stdio.h>
    #include<string.h>
    int main()
    {
        int i,j,n,max,s[101],a[100010];//s[]的容量必须比所需大1 存放 
        while(~scanf("%d",&n))
        {
            memset(s,0,sizeof(s));//需头文件  string.h 
            for(i=1;i<=n;i++)
              scanf("%d",&a[i-1]);
            for(i=0;i<n;i++)
              s[a[i]]++;
            max=0;
            for(j=1;j<=100;j++)
            {
                if(s[j]>max)
                  max=s[j];
            }
            for(j=0;j<=100;j++)
            {
                if(s[j]==max)
                   printf("%d ",j); 
            }
            printf("
    ");
        }
        return 0;
    }

    习题3-2 单词的长度(word)

    输入若干个单词,输出它们的平均长度。单词只包含大写字母和小写字母,用一个或多个空格隔开。

    代码:

    #include<stdio.h>
    #include<string.h>
    int main()
    {
        int n,l,i,sum;
        double m;
        char str[100010];
        while(~scanf("%d",&n))
        {
            m=0;
            sum=0;
            for(i=0;i<n;i++)
            {
                scanf("%s",str);
                l=strlen(str);
                sum+=l;
            } 
            m=(double)sum/n;
            printf("%.2lf
    ",m);
        }
        return 0;
    } 

    习题3-3 乘积的末3位

    输入若干个整数(可以是正数、负数或者零),输出它们的乘积的末3位。这些整数中会混入一些由大写字母组成的字符串,你的程序应该忽略它们。提示:试试看,在执行scanf("%d")时输入一个字符串会怎样?

    输入:AB123CC   BB123123321321          DDD22    888888888888888888888888888ZZ      -411B

    输出:968

    输入:AA-11BBB   D2CCC

    输出:-22

    假定末3位是指,不足3位就输出数字本身,如果是负数则包括负号,比如结果是-12,则输出-12;结果是11,则输出11,结果是0,则输出0;

    代码:

     

    #include<stdio.h>
    int main()
    {
        int a[50]={0};
        int t,c,b,i,sum;
        sum=1;
        while(1)
        {
            c=scanf("%d",&b);
            if(c==0)
            {
                t=getchar();
                if(t=='R')
                   break;
            }//过滤字母,输入大写字母R结束输入 
            else if(b!=0)
            {
                a[i]=b;
                i++;
            }//自动忽略输入的0 
            c=0;
        }
        for(i=0;a[i]!=0;i++)
        {
            sum*=a[i];
        }
        if(sum<=999)
          printf("%d
    ",sum);
        else
          printf("%d
    ",sum%1000);
        return 0;
    }

     

    参考代码:

     题目分析: 
     *     题目难度主要在于参差的数据类型输入。 
     * 题目总思路,使用while语句逐个string作为单词输入。 
     * 然后通过调用函数bool getInt(...)判断该单词是否整数,另外,再利用该函数的形参将正确的整数返回。 
     * 将从函数里面得出的整数与结果相乘,乘后保留末三位整数即可。 
     * 其中,关于如何实现bool getInt(string get, int & nowGet)才是难题。实现方法如下: 
     * 首先,考虑不是整数的情况,1.字符串为空,返回false, 2.是字母或是仅有一个符号。 
     * 除了字符串为空的情况外,我们可以开始考虑字符串不为空的情况,字符串不为空时,存在三种情况, 
     * 第一种,带符号的整数,第二种,不带符号的整数,第三种,不是整数。 
     * 关于这三种情况,可以使用一个if-else if- else语句来实现, 
     * 第一种情况:if ('+' == get[0] || '-' == get[0])带上了符号,可以直接忽略读取第[0]位符号位,然后再 
     *               从最尾位开始读取,读取3位数即可停止,当读取途中不满三位数或者碰上符号位时, 
     *               立即返回。 
     * 第二种情况:if('0' <= get[0] && '9' >= get[0]) 直接是数字的情况下,跟第一种情况的思路基本一致, 
     *               直接从最尾位开始取个位数,次尾位取十位数,倒数第三位取百位数。 
     * 第三种情况:由于不符合需要的整数的转换条件,只需要直接返回false即可. 
     * 另外,如果想将字符型的数字转换成数值,只需要将原来的字符型减去'0'即可得到相对应的数值。 
     **/  
      
    #include <cstring>  
    #include <string>  
    #include <cctype>  
    #include <cmath>  
    #include <iostream>  
      
    using namespace std;  
      
      
    bool getInt(string get, int & nowGet)  
    {  
        int stringLong = get.length();  
        if (0 == stringLong){  
            return false;  
        }  
        nowGet = 0;  
        if ('+' == get[0] || '-' == get[0]){ // 带符号的正数或负数  
            if (0 == (stringLong - 1)){ // 它只包含了一个符号,则直接返回  
                return false;  
            }  
            for (int j = 0, i = stringLong - 1; i > 0 && i >= stringLong - 3; --i, ++j){  
                if ('+' == get[i] || '-' == get[i]){    // 正在循环转换的过程,这个数字不满三位数,遇上了符号,直接跳出  
                    break;  
                }  
                nowGet += int(get[i] - '0') * (int) (pow(double(10), j));  
            }  
            return true;  
        }  
        else if('0' <= get[0] && '9' >= get[0]){ // 直接是数字的情况下  
            for (int j = 0, i = stringLong - 1; i >= 0 && i >= stringLong - 3; --i, ++j){  
                nowGet += int(get[i] - '0') * (int) (pow(double(10), j));  
            }  
            return true;  
        }  
        else{   // 是字母  
            return false;  
        }  
    }  
      
    int main()  
    {  
        string word;  
        long result = 1;  
        while(cin >> word){  
            int temp;  
            if (getInt(word, temp))  
            {  
                result = (result * temp) % 1000;  
            }  
        }  
        cout << result << endl;  
        return 0;  
    }  

    习题3-4

    编程程序读入一行恰好包括一个+或-或*的表达式,输出它的值。运算符保证是二元运算符,且两个运算数均不超过100的非负整数。运算数和运算符可以紧挨也可以有一个或多个空格、TAB隔开。行首尾均可以有空格。提示:选择合适的输入方法可以将问题简化。

    代码:

    #include<stdio.h>
    #define N 1000
    
    int main()
    {
        char *p=NULL;
        char s[N];
        int x,y;
        while(1)
        {
        fgets(s,sizeof(s),stdin);//it will contain '
    ' 
        for(p=s;*p!='
    ';p++)
        {
            if(*p=='+'||*p=='-'||*p=='*')
               break;
        }
        if(*p!='
    ')
        {
            switch(*p)
            {
                case '+':
                    sscanf(s,"%d + %d",&x,&y);//此处的‘+’两边必须有空格才可以吃掉诸如3  +1这种情况 
                    printf("%d
    ",x+y);
                    break;
                case '-':
                    sscanf(s,"%d - %d",&x,&y);
                    printf("%d
    ",x-y);
                    break;
                case '*':
                    sscanf(s,"%d * %d",&x,&y);
                    printf("%d
    ",x*y);
                    break;
            } 
        }
        }
        
        return 0;
    }

    习题3-5 旋转

    输入一个n*n字符矩阵,把它左旋90度后输出

    代码:

    //3-5旋转 
    #include<stdio.h>
    #define N 100
    
    int main()
    {
        int i,j,n;
        char a[N][N];
        while(~scanf("%d",&n))
        {
            for(i=0;i<n;i++)
            {
               for(j=0;j<n;j++)
               {
                     scanf("%s",&a[i][j]);
               }
            }
               
            for(j=n-1;j>=0;j--)
            {
               for(i=0;i<n;i++)
               {
                     printf("%c ",a[i][j]);  
               }
               printf("
    ");
            }
        }
        return 0;
    }

    习题3-6 进制转换1

    输出基数b( 2 <= b <= 10)和正整数n(十进制),输出n的b进制表示

    思路:关键是除留余数法时,结束的条件可以是当前剩下的数字<=基数或者当前剩下的数字的==它的模

    至于逆序输出,可以考虑用递归实现

    代码:

    #include<stdio.h>
    int main()
    {
        int b,n,a[100],i,t;
        while(~scanf("%d %d",&n,&b))
        {
            t=0;
            i=1;
            while(n>=b)//循环条件不可错了!! 
            {
                a[i]=n%b;
                n/=b;
                i++;
            }
            a[i]=n%b;
            t=i;
            for(i=t;i>0;i--)
               printf("%d",a[i]);
            printf("
    ");
        } 
        return 0;
    }
    //递归
    #include<stdio.h>
    int fac(int n,int b)
    {
        if(n>=b)
           fac(n/b,b);
        printf("%d",n%b);
    } 
    int main()
    {
        int b,n;
        scanf("%d %d",&n,&b);
        fac(n,b);
        printf("
    ");
        return 0;
    }

    习题3-7 进制转换2

    输出基数b( 2 <= b <= 10)和正整数n(b进制),输出n的十进制表示

    思路,比如八进制的678,换成十进制就是8*8的0次方+7*8的1次方+6*8的2次方,因此很容易编写

    代码:

    //3-7 进制转换2 
    #include<stdio.h>
    #include<string.h>
    #define N 100
    char s[N];
    int main()
    {
        int n,i,k,l,t;
        
        l=0;
        scanf("%d %s",&n,s);
        for(i=strlen(s)-1;i>=0;i--)//此处i值需取到0!!!! 
        {
            t=s[i]-'0';
            k=strlen(s)-1-i;
            while(k--)
               t*=n;
            l+=t;
        }
        printf("%d
    ",l);
    
    }

    输入一个由小写字母组成的英文单词,输出用手机的默认英文输入法的键盘序列。例如打出pig这个单词  需按1次p,3次i,(稍作停顿后)1次,记为p1i3i1.

    代码:

    #include<stdio.h>
    int main()
    {
        char c;
        int i;
        while(char c=getchar())
        {
            switch(c)
            {
            case 'a':
                printf("a1");
                break;
            case 'b':
                printf("a2");
                break;
            case 'c':
                printf("a3");
                break;
            case 'd':
                printf("d1");
                break;
            case 'e':
                printf("d2");
                break;
            case 'f':
                printf("d3");
                break;
            case 'g':
                printf("i1");
                break;
            case 'h':
                printf("i2");
                break;
            case 'i':
                printf("i3");
                break;
            case 'j':
                printf("j1");
                break;
            case 'k':
                printf("j2");
                break;
            case 'l':
                printf("j3");
                break;
            case 'm':
                printf("m1");
                break;
            case 'n':
                printf("n2");
                break;
            case 'o':
                printf("n3");
                break;
            case 'p':
                printf("p1");
                break;
            case 'q':
                printf("p2");
                break;
            case 'r':
                printf("p3");
                break;
            case 's':
                printf("p4");
                break;
            case 't':
                printf("t1");
                break;
            case 'u':
                printf("t2");
                break;
            case 'v':
                printf("t3");
                break;
            case 'w':
                printf("w1");
                break;
            case 'x':
                printf("w2");
                break;
            case 'y':
                printf("w3");
                break;
            case 'z':
                printf("w4");
                break;
            }        
        }
        printf("
    ");
        return 0;
    } 

    注意每个代码细节  少一个等号,少一个符号 等的 以后不可再犯!

  • 相关阅读:
    Windows 10 字体替换
    Windows 任务栏增加秒显示
    CCProxy v8.0 代理服务器
    Git RPM软件包 && 源码包
    Google Chrome 浏览器最新版本 71.0.3578.98(正式版本) (64 位)
    Linux 查询公网出口IP
    Windows 10 Enterprise LTSC做Windows To Go蓝屏无法进入系统
    Nginx编译./configure翻译
    Windows 10 快捷键
    JDBC连接MySQL
  • 原文地址:https://www.cnblogs.com/lipching/p/3858771.html
Copyright © 2011-2022 走看看