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

关于 输入 问题的注意:

  • 数组在main函数中的定义的无法定义的很大,所以大数据的数组一般定义在main函数外面
  • scanf("%s") 碰到 "\0"、空格、TAB 会停止
  • fgetc(fin) 读取一个打开的文件 fin 碰到 EOF 会停止
    EOF 并不是char类型,因此 fgetc不会返回 char,而是返回 int类型
  • getchar() 从标准输入读取一个字符 == fgetc(stdin)
    Windows 回车符:"\r\n" Windows下读取次回车符,fgetc、getchar 只读取 "\n"
    Linux 回车符:"\n" Linux 下读取Win的回车符,fgetc、getchar 会读取 "\r\n"
    MacOS 回车符:"\r" 同 Linux
  • fgets(buf, maxn, fin) 碰到 "\n"、EOF 会停止
    buf 的声明为 char buf[maxn] fgets函数读取不超过 maxn-1个字符,然后在末尾添加 "\0"
    一个字符都没有读到时 fgets 返回 NULL
  • gets(s) 碰到 "\n"、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]!='\0'; i++){
        if (str[i]=='O'){
            cO++;
            sum += cO;
            printf("%d", cO);
        }else{
            cO=0;
            printf("%d", 0);
        }
        
        if(str[i+1]!='\0'){
            printf("+");
        }else{
            printf("=");
        }
    }
    printf("%d\n", 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("输入格式错误!\n");
        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\n", 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]='\0';
}
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\n",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 \n",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("\n");
    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("\n");
    }
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容