2020级cpp机考模拟题A卷-#题解1

 

为了各位朋友的身心健康(不是),我们按照题目难度顺序来写题解。

 

第一次写题解,希望多点包容和鼓励(恬不知耻


1:谁先输出-4

题意:

输入3个整数,按从大到小的顺序输出,每两个数字间加一个空格。

题解:

输入三个数,用一下排序(冒泡/选择 排序法,或者 A?B:C),然后就可以输出了。

上板子(冒泡排序法):

for (int i = 1;i < n;i++)
{
    for (int j = 1;j <= n - i;j++)
    {
        if (t[j] > t[j + 1])
            swap(t[j], t[j + 1]);
    }
}

13:星号阵列-16

题意:

上下拼接正方形,同位置重合只显示一条边。

题解:

可以看做输出b个,最后输出一行的星号。

上板子(使用循环):

int main()
{
    int a, b;
    cin >> a >> b;
    for (int i = 1;i <= b;i++)
    {
        for (int j = 1;j <= a-1;j++)
        {
            if (j == 1)
            {
                for (int p = 1;p <= a;p++)
                {
                    cout << "*";
                }
                cout << endl;
            }
            else
            {
                for (int p = 1;p <= a;p++)
                {
                    if (p == 1 || p == a)cout << "*";
                    else cout << " ";
                }
                cout << endl;
            }
        }
    }
    for (int u = 1;u <= a;u++)
    {
        cout << "*";
    }
    cout << endl;
    return 0;
}

3:最大的乘积

题意:

找两个数,使它们的乘积最大,然后输出这个乘积。

题解:

依题意,本题给的数据不一定是正数,所以需要通过排序找到最大的两个数跟最小的两个数,分别计算它们的乘积,输出较大的那个。

上板子(依然是冒泡排序法):

for (int i = 1;i < m;i++)
{
    for (int j = 1;j <= m - i;j++)
    {
        if (a[j] > a[j + 1])
            swap(a[j], a[j + 1]);
    }
}//循环结束后,把最后的两个数与最前面的两个数的乘积比较一下,输出较大值。

9:沉迷游戏的大佬

题意:

给出经验总值与各级所需经验,求最终等级。

题解:

这题用循环解,每升一级把这一段所需要的经验减去,注意到了满级之后就不能升级了,所以在循环里特判一下是否满级。

上板子:

int n,x,d=1;//n为人物满级等级,x为经验总值,d为人物等级
cin >> n;
int a[1000] = { 0 };
for(int i=1;i<n;i++)
{
    cin >> a[i];//升级所需经验
}
cin >> x;
int u = 1;//第几级升级到第几级
while (x >= a[u]&&d<n)//特判一下d是否<n,注意!不论你用for还是while,不能写<=。
{
    x -= a[u];
    d++;
    u++;
}
/*这里如果用for,可写为
for(;x >= a[u]&&d<n;d++)    
{
    x-=a[u];
    u++;
}*/
cout << d;

4:最长的妹纸序列

题意:

记录字符串中F最多连续个数。

题解:

录入一个字符串为男女生的队列,用循环依次判断字符是否为F,如果是则count++,如果不是就把count清零。

上板子(循环判断部分):

for (int i = 0;i < s.length();i++)
{
    if (s[i] == 'F')num++;//连续的,下一个为女生,则数量加一 
    else//遇到男生 
    {
        if (num > n)//假若此时的 num > n(n表示连续的最大值)
            n = num; //num 就成为了新的最大值n 
        num = 0;//记得清零重新计数!! 
    }
}
if (num > n) n = num;//假如最后一段是最大值
cout << n << endl;

7:石头剪刀布

题意(开始应用题了,其实算法实现上很简单,然鹅你读不懂题目  /滑稽):

两个人石头剪刀布,其中A开了天眼能预先知道苏学长要出的是石头、剪刀还是布。但是A出石头、剪刀、布的次数有一个上限,石头最多出a次,剪刀最多出b次,布最多出c次(可以选择不出)。求A最多能赢几局。

题解:

题目里说了只需要求A最多赢几句,所以不用管她会输几局,然后简化题意之后这道题就会很简单。

就只要在B出剪刀的时候A出石头,所以A最多能赢的局数就只需要把A的石头次数与B的剪刀次数比较,输出较小值.....以此类推(剪刀跟布也用一样的方法算)......

上板子(真的挺简单的,建议自己看懂了做一遍):

string s;
cin >> s;
int a, b, c, o[4] = { 0 };// o 里面存储 b对应的剪刀、布、石头的次数。 
cin >> a >> b >> c;
for (int i = 0;i < s.length();i++)
{
    if (s[i] == 'j')o[1]++;
    else if (s[i] == 'b')o[2]++;
    else if (s[i] == 's')o[3]++;
}
int sum = 0;
sum += min(o[1], a);// o[1] 代表的是剪刀, a 代表的是石头,min(o[1],a) 就是A玩家用石头最多能赢几句。 
sum += min(o[2], b);
sum += min(o[3], c);
cout << sum << endl;

8:MJ刷题目

题意:

编程竞赛里有n道题目,MJ做第i道题目需要花费t[i]时间。在统计竞赛小分的时候,规定每道题目的小分是:从比赛开始时间到这道题目做出来经历的时间,而MJ的小分将会是每道题的小分之和。假设MJ能够在比赛结束前做出所有题目,并且可以任意调整做题顺序。他想要让自己的小分的值足够小,问小分的最小值是多少?

题解:

很快你就能发现(不是),要小分的值最小,应该把用时短的题目先写了。然后,聪明的你灵光一闪就又知道了,排序、循环后相加。

举个栗子:

假如两道题目,一道题目A用时2分钟,一道题目B用时5分钟。

依据题意,假如先做A,小分为2+(2+5)=9;假如先做B,小分为5+(5+2)=12。

由于每道题的用时里都有前面的用时和,拿第一题举例,这边建议是把第一题的用时乘以题量,就是整个计算中第一题的时间了。对于上面的栗子,我们用这样的方法就可以把它转为:2*2+5*1=9;

上板子(其实主要看题解):

int time = 0;
for (int i = 1;i <= n;i++)//个人习惯, 第一个数组里我一般不存东西,所以从1开始循环。 
{
    time += t[i] * (n-i+1);
}
cout << time;

10:毒虫养成记

题意:

把毒虫放进一个笼子里,让它们自相残杀,最后存活的毒虫就当成最厉害的毒虫。由于毒虫的毒性各有各的不同,即使很弱小的毒虫也有机会干掉很厉害的毒虫。当A毒虫干掉B毒虫以后,会把B毒虫毒性的一半(如果这个值是小数,则保留其整数部分)加入到自己的毒性中,让自己的毒性变得更强大。草原学姐把一堆毒虫装进了笼中,问最后幸存的毒虫最大的毒性是多少?

题解:

虽然通过的人很多,但是由于我在这里卡了一个小时,所以我把这题的位置往后放了。

依据题意,毒虫A杀了B就可以得到它一半的毒性,且遇到小数时直接取整所以不必考虑毒性为奇数。那么,假如A杀了B,A的毒性将表示为A+B/2。你很快就会发现(不是),由于自相残杀过程中,每一个死去的毒虫都会被浪费50%的毒性,而且这个毒性在后面可能还会被 /2 ,例如C杀了上面的A,那么C的毒性为C+A/2+B/4(你看,B的毒性又被浪费了25%)。所以呢你很快就能得到一个重要结论:

让毒性最强的虫子去杀掉所有的虫子

也就是说除了最强的那个虫子保留原先的毒性,其余 /2 后加进去,这样可以最小限度的浪费毒性。

具体操作:一次循环,找出最大值,其余/2,然后再用一次循环,把除以二之后的加进去。

ps:不知道需不需要啊,我特判了m(虫子数量)=1的情况。

上板子:

int m, a[120] = { 0 };
cin >> m;
if (m == 1)    
{
    cin >> m;
    cout << m << endl;
    continue;
}
else
{
    for (int i = 1;i <= m;i++)
    {
        cin >> a[i];
    }
    int sum = 0;
    for (int j = 1;j < m;j++)//排序一次,找出最大值,放在a [m]的位置。 
    {
        if (a[j] > a[j + 1])
            swap(a[j], a[j + 1]);
    }
    for (int i = 1;i < m;i++)//将除了最大的值以外都 /2。 
    {
    a[i] /= 2;
    }
    for (int j = 1;j <= m;j++)//把 /2 之后的毒虫毒性存到最大的毒虫里。 
    {
        sum += a[j];
    }
    cout << sum << endl;
}

6:大规模杀伤性好人卡

题意:

有一个叫01的学长整天被妹纸发好人卡。妹纸丢出的好人卡具有范围杀伤效果。离好人卡越远伤害越小,伤害计算公式是:好人卡的伤害-距离,如果这个值为负的,那么当成0,即没有伤害。

有一天,01被妹纸们堵在一条长度为m的直线道路上,妹纸们对01发了很多张好人卡,每张好人卡具有各自的伤害值以及各自落下的位置。而01只能躲在整点的位置上(即0、1、2、...、m,一共m+1个候选位置),请你帮01找一个位置,让01受到的总伤害最小。

题解:

每一张好人卡的造成的伤害=好人卡的伤害-距离。这里要用到一个之前讲过的函数:abs,使用时记得加上它的头文件 #include<stdlib.h>,也就是abs(好人卡的位置-01学长的位置)。注意!表面上问的是你找个位置,最后输出的却是受到的最小伤害的值。

具体操作:

把每张好人卡的伤害存在数组a[ ]中,好人卡的位置存在数组b[ ]中。然后来一波循环for(int i=0;i<=m;i++)来找到最小伤害mi。

使用 INT_MAX 的话记得加上头文件#include<limits.h>当然你也可以手动输入一个很大的值,去赌它的样例不会比你的大。

上板子(上课讲了个 INT_MAX ,改一下原来的):

int m, p;
cin >> m >> p;
int a[502] = { 0 }, b[502] = { 0 }, c = 0, mi = INT_MAX;// mi 需要有一个初值,不然循环里无法比较。 
for (int i = 1;i <= p;i++)
{
    cin >> a[i];
}
for (int i = 1;i <= p;i++)
{
    cin >> b[i];
}
for (int j = 0;j <= m;j++)
{
    for (int i = 1;i <= p;i++)
    {
        if (a[i] > abs(b[i] - j))
             c += (a[i] - abs(b[i] - j));//c 用于记录在 j 位置下受到的伤害的和。 
    }
    mi = min(c, mi);
    c = 0;//每次循环结束记得清零! 
}
cout << mi << endl;

 


以上为#题解1的全部内容,后面的难题后面会另外再发一个。祝大家学习快乐!!

制作:BDT20040

posted @ 2020-12-20 13:30  流白李  阅读(385)  评论(0编辑  收藏  举报