题解 2020级HAUT新生周赛(二)

题解 2020级HAUT新生周赛(二)
摘要由CSDN通过智能技术生成

写在读前:

  1. 本文主要面对广大c语言初学者,文中除部分特例代码采用c++书写外,大部分代码均采用c语言,大家可放心食用。
  2. 题解内容包含:题目与考点分析、算法思路讲解、参考程序的代码模块设计、注意事项,在以上所有部分都讲解完成后,在一道题的最后会给出参考代码,同时部分题目兼有背景补充或拓展知识,希望可以帮助您全面深入的理解到每一个考点。
  3. 在每道题的讲解部分会给出各种方法非常详细的讲解,从思想到实现逐步分析,请结合代码与文字一起食用
  4. 文中代码均有较为详细的注释,如果在看不懂的情况下,不妨先结合注释转动下灵活的头脑,同时也非常欢迎读者在评论区留下异议或者其他见解。

更新目录:
2020.12.08 修改了部分错别字以及与比赛题目题面不符的内容;
2020.12.10 在文章末尾新添加赛后回顾部分;

A. 阿正的忐忑不安

题目分析:
给出五个正整数,让你判断前四个数与第五个数的大小关系,若是前四个数大于等于第五个数,则输出一段文本,否则输出另一段文本。
本题意在考察最基本的顺序、分支与逻辑设计,难度属于低级梯队

思路讲解:
使用一个if结构即可,判断条件位前四个数的和是否大于第五个数。

对于数据类型的选择,本题考察重点并非数据范围,虽然题目中表明了数据的大小,但对分支语句判断等核心算法并未造成影响。采用int类型的整数即可处理所有输入与运算。

代码模块:
输入与初始化——判断——输出

注意事项:
在输出时有一个略坑的地方需要考虑,便是引号的输出。采用printf函数中输出引号需要用到转义字符的输出方法,类似但又不同于换行符,引号的输出需要采用如下格式:

printf(" \" "):
//运行结果:
 " 

printf函数内写下了一个空格,一个反斜杠,一个引号,一个空格,最后的运行输出结果是一个空格,一个引号,一个空格。

参考代码:
#include<stdio.h>

int sum=0,goal;
//sum来储存阿正的总分; goal来储存录取分数线,即第五个输入值

int main()
{
   
	 for(int i=0;i<4;i++){
   						//四科分数,定义临时变量temp分四次来参与输入与计算
	 	 int temp;
	 	 scanf("%d",&temp);						//输入
	 	 sum+=temp;								//计算
	 }
//以下代码与上等效
/*	 int a,b,c,d;				`				//也可以定义四个变量分别输入计算
	 scanf("%d%d%d%d",&a,&b,&c,&d);
	 sum=a+b+c+d;								*/

	 scanf("%d",&goal);							//输入分数线的值

	 //在if框体内只有一条语句时,可以省略大括号
	 if(sum>=goal) printf("Blessings for your college career!\n");				//大于等于的情况
	 else printf("Blessings for your \"fourth grade\" in high school!\n");		//小于的情况
	 return 0; 									//必须return 0;
}

拓展与背景补充(引自百度百科):

半角字符:半角字符是指一字符占用一个标准的字符位置,通常的英文字母、数字键、符号键都是半角的,半角的显示内码都是一个字节。

转义字符:所有的ASCII码都可以用“\”加数字(一般是8进制数字)来表示。而C中定义了一些字母前加"\"来表示常见的那些不能显示的ASCII字符,如\0,\t,\n等,就称为转义字符,因为后面的字符,都不是它本来的ASCII字符意思了。

B. 阿正的学期准备

题目分析:
题目给了你几种具有一定规律的优惠方案与阿正所持有的金币数量,我们需要根据金币数量组合出可以获利最大的优惠方案,并输出最后连本带利的金币数量
我们细看题目中给出的五种优惠方案,可以发现获赠金币与充值金币是成正比的,只有发现了这个规律,分析才能继续进行,我们后续的算法设计皆是建立在此基础之上的。

本题更加灵活的考察了代码设计能力与最简单的贪心思想,选手可以从分支循环等多个角度灵活地书写代码,难度属于低级梯队中最难的一道题。

而何谓”贪心“思想与具体解题方法,请参考下文:

思路讲解:
获赠金币与充值金币是成正比的基础上,肯定是充值的越多,获利越多。因此我们在已有可以用来充值的金币数固定的情况下,选择充值金币数量多的方案肯定是获利最多的,只要服从”金币数量够,就选最大的“原则,便可以获得最大的利润。

上述叙述就是一个简单的贪心案例,所谓”贪心“,就是当前情况选择可以获利最大的即可,不需要考虑对后续的影响。

在了解了我们设计代码的核心思想后,我们只需要服从上述原则进行设计即可,在这里笔者提供两种思路,读者不必仅局限于此:

在得到可利用最大金币数量后,我们可以自多至少地依次判断金币数量是否满足优惠条件,即从充值金币数量最大的开始判断,如果符合优惠条件,那么便将此项优惠记录,并减少已有的金币数量,继而判断下一项优惠是否满足,直至五项优惠全部判断完。

上文叙述了采用纯分支语句的判断方法,我们按照从多到少的顺序写下五个分支语句便可。同时,我们也可以将这些参数存储到数组中,然后采用循环依次判断是否符合优惠条件:

首先建立两个数组分别来存储充值所需金额与对应的获利金额,此处要注意,我们循环的方向要与上文分支中判断的方向一致,即仍然从大到小进行判断,所以我们在存储数据时可以将数据倒置一下,即将第五种优惠的参数存储到数组下标位0的位置,将第一种优惠的参数存储到数组下标为4的位置。继而,再进行循环依次遍历。

并且对于数据类型的选择,与本次比赛大部分题目相同,本题中明确给出了所有数据均在整形范围内,因此选择整形便足够了。

代码模块:
输入与初始化——数据处理——输出

注意事项:
分支语句的写法不必多言,只需要在进入当前分支后记得减去花费掉的金币数,加上获得的金币数即可。
但若是采用循环的整体框架,则写法更加灵活,可以在循环语句里进行分支判断,也可以进行其他更优的操作。

参考代码:
分支书写:
#include<stdio.h>

int n;											//n即为最初的金币总数

int main()
{
   
	 scanf("%d",&n);
	 int now=n,result=n;
	 //now为执行过程中实时更新的金币数量, result即为购物卡中实时更新的金币数量,即"连本带利"的金币数
	 //此处将result初始化为n,后续计算中只用考虑获利即可;
	 //如果初始化为0,则在分支中不仅要添加"本金的部分", 在遍历完五个方案后,还要加上五个方案没花完的"剩余的部分"
	 
	 if(now>=648) now-=648,result+=108;			//从多到少依次判断, 如果符合条件更改两个参数的值
	 if(now>=324) now-=324,result+= 54;
	 if(now>=108) now-=108,result+= 18;
	 if(now>= 36) now-= 36,result+=  6;
	 if(now>=  6) now-=  6,result+=  1;
	 
	 printf("%d\n",result);						//输出结果
	 return 0;									//必须return 0;
}
循环书写:
#include<stdio.h>
 
int n,pointer=0;								//与上同理,n为初始金币数,而pointer则记录遍历到哪种优惠情况
int cost[6]={
   648,324,108,36,6,0},extra[6]={
   108,54,18,6,1,0};
//cost存储需要充值数量,extra存储额外获利的金币数量;
//并且将最后一位留给0的位置,pointer指向最后一位,便说明金币已经花完了,不能再进行充值了
 
int main()
{
   
     scanf("%d",&n);
     int now=n,result=0;						//now为过程中实时更新的所持有的金币数量,result为实时更新的购物卡中金币总数
     while(pointer<6){
   							//只有pointer小于5时才能进行充值
         while(cost[pointer]>now) pointer++;	//寻找当前金币数可以选择的最大优惠方案,包括数组第六位的"0"方案,即代表不能再进行充值
         now-=cost[pointer];					//更新两个参数的值,此处result需要"连本带利"地进行更新
         result+=(extra[pointer]+cost[pointer++]);
     }
     result+=now;								//并且最后加上能享受的优惠都享受后, 剩余的金币数
     printf("%d\n",result);						//最后输出结果
     return 0; 									//必须return 0;<
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值