2021年冬季PAT乙级题解(C语言)

感兴趣的小伙伴可以先看看我的这篇文章哦,打开看看,说不定能帮到你一些~~

金陵科技学院软件工程学院软件工程专业

前言:趁着状态好,重新做了一遍这套真题。这次做的时候顺顺利利的AC掉了1,2,4,5四道题目,然而离谱的是,上次考试时我最后改对的第三题,这次居然怎么也改不对。

更新于2022年4月4日晚:
换了个角度思考,总算用C语言把这个第三题给AC了,同时也改了一下先前版本里第二题的一个很愚蠢的地方。

:这套真题的C++版本的满分代码可以参考我当时考完发的这篇文章:2021年冬季PAT乙级满分复盘(不是我的代码)

7-1 自动打包机 (15 分)
在这里插入图片描述
一条哈密瓜自动打包流水线的工作程序是这样的:首先系统设定每箱哈密瓜应该有的总重量 W;然后传送带将一只只哈密瓜输送到一个自动称重设备上,根据称重结果进行以下操作:

如果称上的总重量正好达到 W,则将称上的所有哈密瓜装箱送走;
如果称上的总重量还不到 W,则将这只哈密瓜留在称上;
如果称上的总重量超过了 W,则将这只哈密瓜放到一边暂不处理。

本题就请你写个程序统计一下,究竟有多少只哈密瓜被装了多少箱?

输入格式:
输入第一行给出两个正整数 N(≤1000)和 W(≤10^4),分别为传送带上哈密瓜的数量和每箱的规定重量(克)。随后一行给出 N 个正整数,是传送带上每只哈密瓜的重量,单果重量不超过 2000 克。假设传送带按照输入的顺序传送哈密瓜到称重设备。

输出格式:
在一行中输出成功装箱的箱子数量和被装箱的哈密瓜的数量。数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:
12 5000
2000 1500 1800 1000 1800 500 1900 1500 2000 1600 2000 2000

输出样例:
2 7

样例说明:
第 1、2、4、6 只瓜正好一箱;第 7、8、10 只瓜正好一箱。

AC代码:

#include <stdio.h>
int main(){
    int n, w, i, x, sum = 0, cnt_xz = 0, cnt_hmg = 0, m = 0;
    scanf("%d %d", &n, &w);
    for(i = 0; i < n; i++){
        scanf("%d", &x);
        int temp = sum + x;
        if(temp < w){
            sum += x;
            cnt_hmg++;
            m++;
        }else if(temp == w){
            cnt_xz++;
            cnt_hmg++;
            sum = 0;
            m = 0;
        }
    }
    if(m) cnt_hmg -= m;
    printf("%d %d", cnt_xz, cnt_hmg);
    return 0;
}

7-2 用药统计 (20 分)
在这里插入图片描述
上图是知乎上的一个问题:“在计算机中,有没有那种把很多病历导入,然后用计算机统计哪种药用的多的语言。?”虽然这个问题有错别字和标点符号错误,但好心的你还是帮他做一个吧 —— 给定 N 位病人病历中的用药纪录,请你统计被用的最多的那种药,并且列出其治疗过的疾病。

输入格式:
输入第一行给出正整数 N(≤10^4),为病历个数。随后 N 行,每行给出一条病历信息,格式如下:
疾病编号 K 药物编号1 药物编号2 …… 药物编号K
其中疾病编号是一个 4 位数字,题目保证每条病历中的疾病编号都是不同的;K 是不超过 10 的正整数,为该疾病用药的种类数;药物编号是一个以 MD 开头、后面跟 5 位数字的字符串。题目保证在一条病历中没有重复的药物编号。

输出格式:
首先在第一行输出被用的最多的那种药的编号,及其被用的次数,其间以一个空格分隔。如果有并列,则只输出编号最小(即 MD 后那串数字最小)的那个。随后按照输入的顺序输出该药物治疗过的疾病的编号,每行一个。

输入样例:
5
0012 3 MD10031 MD99132 MD42107
1024 2 MD99132 MD34821
2048 2 MD27845 MD10031
0149 2 MD34821 MD55802
0035 3 MD55802 MD99132 MD10031

输出样例:
MD10031 3
0012
2048
0035

AC代码:

#include <stdio.h>
struct bingli{
    int bing, k, yao[10];
}bl[10000];
int main(){
    int n, i, j, cnt[100000] = {0}, max = 0, maxbh;
    scanf("%d", &n);
    for(i = 0;i < n;i++){
        scanf("%d %d ", &bl[i].bing, &bl[i].k);
        for(j = 0; j < bl[i].k;j++){
            /*
               getchar();
               getchar();
               
               更新于2022年4月4日晚:
               
               原本我这里写的是如上所示的两行getchar(),作用就是一个用来输入M,一个用来输入D。
               但其实直接在这里输入的前面写上MD就好。
               原本是贴的考试时候的代码,当时没反应过来,写的两行getchar(),题解里也就直接这么拉过来了。
               直到今天有人问我这个,我才意识到不对劲,正巧我在想这份的第三题,于是顺带一起改一下这里。
            */ 
            scanf("MD%d ", &bl[i].yao[j]);
            cnt[bl[i].yao[j]]++;
            max = max > cnt[bl[i].yao[j]] ? max : cnt[bl[i].yao[j]];
        }
    }
    for(i = 0;i < 100000;i++){
        if(cnt[i] == max){
            maxbh = i;
            break;
        }
    }
    printf("MD%05d %d\n", maxbh, max);
    for(i = 0; i < n;i++){
        for(j = 0; j < bl[i].k;j++){
            if(bl[i].yao[j] == maxbh){
                printf("%04d\n", bl[i].bing);
                break;
            }
        }
    }
    return 0;
}

7-3 五彩斑斓的黑 (20 分)
在这里插入图片描述
在这里插入图片描述
AC代码:
上次线下考的时候也是用C语言写的,最后这题做出来了而且没有超时。这次做的时候感觉和我上次写出来的代码差不多,然而最后两个点却怎么也改不对。这里贴出我这次用C语言写的14分的代码,还请各位大佬帮忙看看怎么改这个超时。
在这里插入图片描述

#include <stdio.h>
#include <string.h>
int main(){
    char color[100000][12], res[100000][12];
    int n, i, j, cnt = 0;
    scanf("%d", &n);
    for(i = 0;i < n;i++){
        scanf("%s", color[i]);
        int flag = 1;
        for(j = 0;j < i;j++){
            if(!strcmp(color[i], color[j])){
                flag = 0;
                break;
            }
        }
        if(flag) strcpy(res[cnt++], color[i]);
    }
    printf("%d\n", cnt);
    for(i = 0;i < cnt;i++){
        if(i) printf(" ");
        printf("%s", res[i]);
    }
    return 0;
}

更新于2022年4月4日晚:
清明假期想了想这道题,还是想不到别的纯C语言的写法。于是想着去翻翻其它乙级题目的题解,看看能不能有灵感。突然看到某位博主在题库里的某一题中用到了三维数组这个东西,顿时眼前一亮,下一秒我就反应过来好像这题就很适合用三维数组,于是立马去买了考试卷,重新审视了一下这道题,果然还是AC掉了。这次,我从整数的角度上处理这题的输入输出,用三维数组来标记每个颜色是否出现过,再开三个一维数组分别保存一个未出现过颜色的RRR、GGG、BBB的值,最后按照格式输出就行。

AC代码:

#include <stdio.h>
/*
  这个三维数组注意要开成全局变量,
  因为函数内部申请的局部变量来自系统栈,允许申请的空间较小,
  而函数外部申请的全局变量来自静态存储区,允许申请的空间较大,
  这个三维数组是256 * 256 * 256的,那么可想而知要把它定义成全局变量。
*/
int color[256][256][256] = {0};
int main(){
    int n, i, cnt = 0;
    int R, G, B;
    int RRR[100000], GGG[100000], BBB[100000];
    scanf("%d", &n);
    for(i = 0;i < n;i++){
        scanf("%d.%d.%d ", &R, &G, &B);
        if(color[R][G][B] == 0){
            RRR[cnt] = R;
            GGG[cnt] = G;
            BBB[cnt] = B;
            cnt++;
        }
        color[R][G][B]++;
    }
    printf("%d\n", cnt);
    for(i = 0;i < cnt;i++){
        if(i) printf(" ");
        printf("%03d.%03d.%03d", RRR[i], GGG[i], BBB[i]);
    }
    return 0;
}

7-4 假新闻 (20 分)
在这里插入图片描述
在这里插入图片描述
AC代码:

#include <stdio.h>
int main(){
    int n, m, i, o[10000], cnt_jwz[10000], max = 0, bh;
    scanf("%d %d", &n, &m);
    while(m--){
        int cnt_gd[20001] = {0};
        for(i = 0;i < n; i++){
            scanf("%d", &o[i]);
            if(o[i] < 0) o[i] = o[i] * -1 + 10000;
            cnt_gd[o[i]] ++;
        }
        int min = 100000;
        for(i = 0;i < n; i++) min = min < cnt_gd[o[i]] ? min : cnt_gd[o[i]];
        for(i = 0;i < n; i++){
            if(min == cnt_gd[o[i]]) cnt_jwz[i]++;
        }
    }
    for(i = 0;i < n; i++){
        if(cnt_jwz[i] > max){
            max = cnt_jwz[i];
            bh = i;
        }
    }
    printf("%d", bh + 1);
    return 0;
}

7-5 静态链表的秩 (25 分)
在这里插入图片描述
AC代码:

#include <stdio.h>
int main(){
    int n, i, t, m = -1;
    scanf("%d", &n);
    int k = n, res[100000], qian[100000], x;
    for(i = 0;i < n;i++){
        scanf("%d", &x);
        qian[x] = i;
    }
    while(k--){
        t = qian[m];
        res[t] = k;
        m = t;
    }
    for(i = 0;i < n;i++){
        if(i) printf(" ");
        printf("%d", res[i] + 1);
    }
    return 0;
}
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spiderman_94

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值