算法竞赛入门经典——第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;
} 

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

原文地址:https://www.cnblogs.com/lipching/p/3858771.html