1014. 福尔摩斯的约会
题目分析
这道题主要难度地方在于把题目的意思理解明白。题干有些长,叙述也有些绕,需要耐心仔细。
总结起来,需要满足下面几个条件:
- 日期判定:前两个字符串中第一对相同的大写英文字母,此外由于日期只有7天,按题目中的方法,必须满足大写字母是A~G(前7个英文字母)
- 小时数判定: 是前两个字符串中第二对相同的数字或大写字母A~N(前13个英文大写字母)
- 分钟数判定: 相对简单清晰,找出后两个字符串,第一次出现相同的字母的位置。但是要注意位置是从0开始计的,不要惯性地在输出时+1
明确了题目的要求后,编写代码就会容易很多。在输出时,需要注意如果小时和分钟数不是两位数要补0,这个可以直接用printf函数%02d来解决,设置宽度为2,不足时用0补充即可。
源代码
#include <stdio.h>
#include <ctype.h>
int main()
{
char day[7][4]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
char code[4][61]; //用int 储存4组字符串
for(int i=0;i<4;++i) //读入字符串
gets(code[i]); //未遇到文件尾或换行符时继续读取
int count=0;
int dayOrder=-1,hour=-1,minute=-1;
while(code[0][count]!='\0'&&code[1][count]!='\0'){
if(code[0][count]==code[1][count]){
int judge=code[1][count];
if(dayOrder==-1&&'A'<=judge&&judge<='G') //还未发现日期,并命中大写字母A~G
dayOrder=judge-'A'; //减去A的ASCII码,对应日期序号
else if(dayOrder>-1){
if('0'<=judge&&judge<='9') {hour=judge-'0';break;} //若是数字
else if('A'<=judge&&judge<='N') {hour=judge-'A'+10; break;} //若是大写字母A~N
}
}
count++;
}
count=0;
while(code[2][count]!='\0'&&code[3][count]!='\0'){
if(code[2][count]==code[3][count]&&isalpha(code[2][count])){
minute=count; //题目要求从0开始计数
break;
}
count++;
}
printf("%s %02d:%02d",day[dayOrder],hour,minute);
return 0;
}
1015. 德才论
题目分析
这道题主要的挑战在于排序算法,我测试了一下,第一次自己写了个插入排序,虽然平均时间复杂度也是 ,但只能部分测点通过,有两个测试点会超时。后来看网上都用了< algorithm >头文件里的sort排序函数,这个排序函数用的是快速排序,复杂度最差也是 ,可见有些测点的数据设置还是挺苛刻的。关于这个函数的内容网上很容易搜到,就不多说了。
源代码
#include <stdio.h>
#include <algorithm>
struct candidate{
int id;
int moralScore; //德分
int intelScore; //才分
int sum;
};
bool compare(candidate& a,candidate& b);
int main()
{
int caseNumber,boundLow,boundHigh; //分别记录总人数,最低分数线和最高分数线
int count=0; //记录达线总人数
int num[4]={0,0,0,0}; //记录四类考生总人数
scanf("%d %d %d",&caseNumber,&boundLow,&boundHigh);
candidate *scoreClass[4]; //四类考生排序记录
for(int i=0;i<4;++i)
scoreClass[i]=new candidate[caseNumber];
candidate *info=new candidate[caseNumber];
for(int i=0;i<caseNumber;++i){
scanf("%d %d %d",&info[i].id,&info[i].moralScore,&info[i].intelScore);
info[i].sum=info[i].moralScore+info[i].intelScore;
}
//根据分数情况分类
for(int i=0;i<caseNumber;++i){
if(info[i].moralScore>=boundLow&&info[i].intelScore>=boundLow){
count++; //过线人数+1
if(info[i].moralScore>=boundHigh){ //德分过优取线
if(info[i].intelScore>=boundHigh) //才分也过,德才全尽,第一类
scoreClass[0][num[0]++]=info[i]; //新元素进入数组
else //否则第二类
scoreClass[1][num[1]++]=info[i];
}
else if(info[i].intelScore<=info[i].moralScore) //才德兼亡,但德胜才,第三类
scoreClass[2][num[2]++]=info[i];
else //其余为第四类
scoreClass[3][num[3]++]=info[i];
}
}
for(int i=0;i<4;++i) //排序
std::sort(scoreClass[i],scoreClass[i]+num[i],compare);
//输出
printf("%d\n",count);
for(int i=0;i<4;++i)
for(int j=0;j<num[i];++j)
printf("%d %d %d\n",scoreClass[i][j].id,scoreClass[i][j].moralScore
,scoreClass[i][j].intelScore);
//释放空间
for(int i=0;i<4;++i)
delete []scoreClass[i];
delete []info;
return 0;
}
bool compare(candidate &a,candidate& b)
{
if(a.sum!=b.sum) return a.sum>b.sum; //总分降序排列
if(a.moralScore!=b.moralScore) return a.moralScore>b.moralScore; //德分降序排列
return a.id<b.id; //id升序排列
}
1016. 部分A+B
题目分析:
这道题相对而言比较容易,按题意按部就班编写。求 或者 的方法是,每次除以10,根据余数是否等于 或 来判断是否命中,命中之后按当前幂次情况累加求和即可。
源代码
#include <stdio.h>
int main()
{
int a,Da,b,Db;
scanf("%d %d %d %d",&a,&Da,&b,&Db);
int pa=0,pb=0;
int res;
int plus=1; //用来记录10^x的值
while(a){
res=a%10; //余数
if(res==Da){
pa+=plus*Da;
plus*=10;
}
a/=10; //更新a
}
plus=1; //重置
while(b){
res=b%10; //余数
if(res==Db){
pb+=plus*Db;
plus*=10;
}
b/=10; //更新b
}
printf("%d",pa+pb);
return 0;
}
1017. A除以B
题目分析:
乍一看可能有些复杂,位数如此大不可能用任何现有的数据类型存储,只能考虑用字符读取然后计算。
这里我采用的算法就是将手动求除法的竖式用代码实现了一下。用一个int数组来存各位数,注意要将ASCII码转换成对应的数字。
首先将余数
置为0,从第一位(最高位)开始,每次新一轮除法的被除数等于上一次除法的余数
乘以10加上当前位上的数字
。即:
然后进行除法,更新余数,把相应的此轮除法得到的商存入对应的数组中,以此循环,直到计算到最后一位。
在平时的手动除法中,我们一般最高位的0都省略掉了,而采用了借位,实际上的方法是完全一致的。在产生最高位除法借位的情况下,也就对应着第一位除法商是0,正常计算,存入数组即可,但在输出时要注意可能不会输出这个0。
源代码
#include <stdio.h>
int longDivide(int* dividend,int len,int divisor,int* quotient,int& quoLen);
int main()
{
int longNum[1001];
int divisor;
int quotient[10000];
int resident;
int len=0;
int quoLen=0; //记录最后商的长度
while((longNum[len]=getchar())!=' '){
longNum[len]-='0'; //将对应的ASCII码转换成数字
len++;
}
scanf("%d",&divisor);
resident=longDivide(longNum,len,divisor,quotient,quoLen);
if(quoLen==1&"ient[0]==0) printf("0"); //若商长度只有1,且第一位为0,那么商就是0
else{
int i=0;
if(quotient[0]==0) //若首位记录为0(最高位除法有借位)
i=1;
while(i<quoLen){
printf("%d",quotient[i]);
i++;
}
}
printf(" %d",resident);
return 0;
}
int longDivide(int* divarr,int len,int divisor,int* quotient,int& quoLen)
{
int res=0;
quoLen=0; //商数组的长度置为0
int i=0;
while(i<len){ //对每一位依次做除法
int dividend=res*10+divarr[i];
res=dividend%divisor;
quotient[quoLen++]=dividend/divisor;
i++;
}
return res;
}