• 「算法竞赛入门经典 第二版」第 3 章 数组和字符串 习题解答


    关于 输入 问题的注意:

    • 数组在main函数中的定义的无法定义的很大,所以大数据的数组一般定义在main函数外面
    • scanf("%s") 碰到 ""、空格、TAB 会停止
    • fgetc(fin) 读取一个打开的文件 fin 碰到 EOF 会停止
      EOF 并不是char类型,因此 fgetc不会返回 char,而是返回 int类型
    • getchar() 从标准输入读取一个字符 == fgetc(stdin)
      Windows 回车符:" " Windows下读取次回车符,fgetc、getchar 只读取 " "
      Linux 回车符:" " Linux 下读取Win的回车符,fgetc、getchar 会读取 " "
      MacOS 回车符:" " 同 Linux
    • fgets(buf, maxn, fin) 碰到 " "、EOF 会停止
      buf 的声明为 char buf[maxn] fgets函数读取不超过 maxn-1个字符,然后在末尾添加 ""
      一个字符都没有读到时 fgets 返回 NULL
    • gets(s) 碰到 " "、EOF 会停止
      从标准输入中读取字符串,但 没有指明读取的最大字符数
      会不停的往 s 存储内容,不管是否存储的下「存在缓冲区溢出漏洞」
      C11标准里 gets函数已经删除

    3-1 「UVa1585」得分:给出一个由O和X组成的串(长度为1~80),统计得分。每个O得分为目前连续出现的O的个数,X得分为0.例如,OOXXOXOOOX的得分为 1+2+0+0+1+0+0+1+2+3

    #include<stdio.h>
    #define MAX 100
    int main() {
        char str[MAX];
        scanf("%s", str);
        int sum,cO;
        sum=cO=0;
        for (int i=0; str[i]!=''; i++){
            if (str[i]=='O'){
                cO++;
                sum += cO;
                printf("%d", cO);
            }else{
                cO=0;
                printf("%d", 0);
            }
            
            if(str[i+1]!=''){
                printf("+");
            }else{
                printf("=");
            }
        }
        printf("%d
    ", sum);
        return 0;
    }
    

    3-2 「UVa1586」分子量:给出一种物质的分子式(不带括号)求分子量。本题分子只包含4种原子,分别为C,H,O,N 分子量为分别为12.01,1.008,16.00,14.01(单位:g/mol)例如:C6H5OH 的分子量为 94.108g/mol

    #include<stdio.h>
    #include<string.h>
    #include<ctype.h>//int isdigit(int,char)需要的头文件
    #define MAX 20
    double getWeight(char c){
        double w = 0;
        switch (c) {
            case 'c':
            case 'C': w = 12.01;break;
            case 'h':
            case 'H': w = 1.008;break;
            case 'o':
            case 'O': w = 16.00;break;
            case 'n':
            case 'N': w = 14.01;break;
        }
        return w;
    }
    int main() {
        char str[MAX];
        scanf("%s", str);
        if(isdigit(str[0])){//isdigit判断字符是不是数字
            printf("输入格式错误!
    ");
            return 0;
        }
        double weight = 0;
        double sum = 0;
        for (int i=0; i<strlen(str);i++){
            int num = 1;
            for(int pre=0; isdigit(str[i]);i++){
                num = pre*10+str[i]-'0';
                pre = num;
            }
            sum += num * weight;   //weight = str[i-1]'s weight
            if(i<strlen(str)) weight = getWeight(str[i]);  //weight = str[i]'s weight
        }
        sum += weight;//加上最后一次循环的原子量
        printf("分子量为:%.3lfg/mol
    ", sum);
        return 0;
    }
    

    3-3「UVa1225」数数字:把前n(n<=1000)个整数顺次写在一起:89101112...数一数09各出现多少次(输出10个整数,分别是09出现的次数)

    #include<stdio.h>
    #include<string.h>
    #define MAX 1000000
    char str[MAX];
    // windows下独有一个 char *ito(int 要转换的数,char *转换后的数组位置,int 转换后的进制数) 函数
    // 它在 stdlib.h 中,是 将数字转化为字符串 的函数
    void itoa(int n,char *s){
        int sign;
        char tmp[100];
        if((sign=n)<0)//记录符号
            n=-n;//使n成为正数
        int i=0;
        do{
            tmp[i++]=n%10+'0';//取下一个数字
        }while((n/=10)>0);//删除该数字
        if(sign<0) tmp[i++]='-';
        for(int j=i-1,k=0; j>=0; j--,k++)//生成的数字是逆序的,所以要逆序输出
            s[k] = tmp[j];
        s[i]='';
    }
    int main() {
        int n;
        scanf("%d",&n);
        int count[10]={0};//每个标号存储对应的数字出现的次数
        char tmp[10];
        for (int i=n; i<=10000; i++) {
            itoa(i, tmp);
            strcat(str,tmp);//将字符串tmp添加到str后面,并返回添加后的数组
        }
        for(int i=0; i<strlen(str); i++)
            count[str[i]-'0']++;
        for (int i=0; i<10; i++)
            printf("Times of %d is %d
    ",i,count[i]);
        
        return 0;
    }
    //注:本题也可直接根据数学方法求出,不过公式的推导较浪费时间,方法不在列出
    

    3-4「UVa455」周期串:如果一个字符可以由某个长度为k的字符串重复多次得到,则称该串以k为周期。例如:abcabcabcabc 以3为周期(注意:它也以6和12为周期)输入一个长度不超过80的字符串,输出其最小周期。

    #include<stdio.h>
    #include<string.h>
    #define MAX 80
    int main() {
        char str[MAX];
        scanf("%s",str);
        int len = strlen(str);
        for (int i=1; i<len; i++){
            if (len%i == 0){ //如果i为最小周期,那么字符串长度必定是i的整数倍
                int flag = 1;
                for (int j=i; j<len; j++)  //判断数组是否已i为周期
                    if (str[j-i] != str[j]) flag = 0;
                    else break;
                if (flag){
                    printf("最小周期为:%d 
    ",i); //输出对应的周期
                    break; //如果flag不为0,那么退出循环
                }
            }
        }
        return 0;
    }
    

    开灯问题:有n盏灯,编号为1~n。第1个人把所有灯打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯将会打开,打开的灯将会关掉),依次类推。一共有k个人,问最后有那些灯开着?输入n和k,输出 开着 的灯的编号。k<=n<=10000
    样例输入
    7 3
    样例输出
    1 5 6 7

    #include<stdio.h>
    #include<string.h>//memset
    #define MAX 1010
    int a[MAX];
    int main()
    {
        int n, k, first=1;
        memset(a,0,sizeof(a));//把数组清 0
        scanf("%d%d",&n,&k);
        for(int i=1; i<=k; i++)
            for(int j=1; j<=n; j++)
                if(j%i == 0) a[j] = !a[j];
        for(int i=1; i<=n; i++)
            if(a[i]){
                if(first) first=0;//避免输出多余空格
                else printf(" ");
                printf("%d", i);
            }
        printf("
    ");
        return 0;  
    }
    

    蛇形填数:在nxn方阵里填入1,2,3,...,nxn,要求填成蛇形。例如:n=4时的方阵为:「下面方阵,多余的 '_' 只是为了便于观察,不必严格输出,n<=8」
    10 11 12 1
    _9 _6 13 2
    _8 15 14 3
    _7 _6 _5 4

    #include<stdio.h>
    #define MAXN 50
    int main()
    {
        int a[MAXN][MAXN]={0};//给数组清0
        int num,n,x,y;
        scanf("%d",&n);
        num = a[x=0][y=n-1] = 1;
        while(num < n*n){
            while(x+1<n && !a[x+1][y]) a[++x][y] = ++num;
            while(y-1>=0 && !a[x][y-1]) a[x][--y] = ++num;
            while(x-1>=0 && !a[x-1][y]) a[--x][y] = ++num;
            while(y+1<n && !a[x][y+1]) a[x][++y] = ++num;
        }
        for(x=0; x<n; x++){
            for(int y=0; y<n; y++)
                printf("%5d",a[x][y]);
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    ssh端口转发
    linux git命令安装
    linux git命令
    linux cpio命令
    linux 抓包工具
    js 深拷贝 ,浅拷贝
    vue $router 打开新窗口
    excel常用操作
    Kafka Topic的增删改查操作
    linux上删除文件名乱码的文件
  • 原文地址:https://www.cnblogs.com/liquor1993/p/5152129.html
Copyright © 2020-2023  润新知