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,使用时记得加上它的头文件 #
具体操作:
把每张好人卡的伤害存在数组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