第五届计算机能力挑战赛国赛C语言组题解(专科组)

前言:
  前两天计算机能力挑战赛国赛结束了,拿着题做了一遍,发现难度真的不大,比省赛简单多了,只是有时候可能有的同学拿着题,没认真仔细去读,或者说紧张了导致自己发挥不好吧。以下是个人的题解,若有不足之处,欢迎指正。

题目:

    • 第一题:最小值
    • 第二题:集合相等
    • 第三题:算术
    • 第四题:时间
    • 第五题:扑克牌

第一题:最小值

题目描述
在已知的若干个整数当中,你能计算出谁最小吗?
输入格式
输入数据包含多个整数(最少1个,最多1000个),用空格隔开。
输出格式
Min=x,其中的x为输入数据中最小的那个整数。
输入样例1:
1 2 3 4 5 6
输出样例1:
Min=1
输入样例2:
200 300 150 50 80 62 75 31 2023 11 25
输出样例2:
Min=11
输入样例3:
0
输出样例3:
Min=0

思路:
  这算得上是打卡题吧,唯一一点就是如何判断输入结束,可以通过 scanf 的返回值去判定,当返回值为 EOF(文件末尾) 就表示结束了

代码:

#include
int main(){
	int n;
	int min = 1e9;//初始化最小值为很大的数
	while(scanf("%d", &n) != EOF){
		min = n < min ? n : min;
	}
	printf("Min=%d\n",min);
	return 0;
} 

第二题:集合相等

题目描述
对于两个元素个数相同的集合,如果两个集合中包含的元素都是一样的,我们就说这两个集合是相等的;否则集合不等。
输入格式
第1行是一个正整数 M(M<=100),然后接下来的第2行是 M 个整数,代表集合 A(集合内没有相同元素,没有空集合)。
第3行是一个正整数 N(N<=100),然后接下来的第4行是 N 个整数,代表集合 B(集合内没有相同元素,没有空集合)。
输出格式
若两个集合相等,输出 Equal!,否则输出 Not Equal!。
输入样例1:
4
1 2 3 4
4
4 3 2 1
输出样例1:
Equal!
输入样例2:
5
1 2 3 5 4
5
4 3 2 1 0
输出样例2:
Not Equal!
输入样例3:
3
1 2 3
4
1 2 3 4
输出样例3:
Not Equal!

思路:
  这题也很简单,理解好题意就行,集合相等的条件是元素一模一样,元素个数也一样。那么我们可以利用 qsort 将两个集合都排个序,从头扫描,若某个位置上两个集合的元素不相等,就说明不相等,扫描完了都没有找到不相等的元素,则说明相等。关键点在于对 qsort 函数以及比较函数的掌握度

代码:

#include
#include
int a[105], b[105];
int isOK(int a[], int b[], int p, int q);
int cmp (const void * a, const void * b);
int main(){
	int m, n;
	//接收
	scanf("%d", &m);
	for(int i = 0; i < m; i++){
		scanf("%d", &a[i]);
	}
	scanf("%d", &n);
	for(int i = 0; i < n; i++){
		scanf("%d", &b[i]);
	}
	//排序
	qsort(a, m, 4, cmp);
	qsort(b, n, 4, cmp);
	if(isOK(a, b, m, n)){
		printf("Equal!\n");
	}else {
		printf("Not Equal!\n");
	}
	return 0;
}
//判断两个集合是否相等
int isOK(int a[], int b[], int m, int n){
	if(m != n) return 0; //若元素个数都不相等则一定不相等
	for(int i = 0; i < m;i ++){//i < m 或 i < n 均可
		if(a[i] != b[i]) return 0;
	}
	return 1;	//返回1一定是没有找到不相同的元素
}
//比较函数升序的常规写法,背下来即可
int cmp (const void * a, const void * b){
   return ( *(int*)a - *(int*)b );
}

第三题:算术

题目描述
老师给小明布置的家庭作业是一些算术题,你能通过编程计算出结果吗?
输入格式
输入是在一行中写出的关于整数的算式,只包含加减两种运算,算式中间没有空格,算式的最后是=。
最短的算式是两个数的运算,算式最长不超过100个数,算式中的整数和运算结果不超出int型数据。
输出格式
输出算式的结果,一个整数。
输入样例1:
1+2=
输出样例1:
3
输入样例2:
1-2-3=
输出样例2:
-4
输入样例3:
1+2-3+4+5-6=
输出样例3:
3
输入样例4:
8000+10000-20000+6000=
输出样例4:
4000

思路:
  本题稍微麻烦一点,需用将整个式子当作字符串,然后逐个字符地处理,若当前字符是数字 0~9 ,那么就将计算结果存起来,若当前字符是 ‘+’ 或 ‘-’,那么将上一次的数字结果,往总和里计算

代码:

#include
#include
char all[1000];//存整个式子的字符串 
int main(){
	int result = 0, cnt = 0;//cnt用来记录下标 
	gets(all);//接收字符串 
	char pre_flag = '+';  //当前运算符,初始为‘+’ 
	while(pre_flag != '='){ 
		int sum = 0;//用来记录当前数的 
		while(all[cnt] >= '0' && all[cnt] <= '9'){
			sum = sum * 10 + all[cnt] - '0';
			cnt++;
		}
		//算出当前数后,就可以根据前一个运算符去运算了 
		if(pre_flag == '+'){
			result += sum;
		}else result -= sum;
		//更新运算符 
		pre_flag = all[cnt];
		cnt++;
	}
	printf("%d\n",result);
	return 0;
} 

第四题:时间

题目描述:
人生的黄金时间在青年,“一寸光阴一寸金”。学习是一种投资,而时间是最宝贵的投资资本。珍惜时间吧,用学习塑造美好的未来。已知某个时刻(以分钟为单位),你知道 n 分钟以前是什么时间吗?
输入格式输入为形如HH:MM的某一时间和一个正整数N (N<=200000)。其中HH表示小时(以24小时制表示),MM表示分钟。输出格式输出为形如HH:MM的时间,表示输入数据中时间在经过 N 分钟以前的时间。注意输出时小时和分钟时都以 2 位整数形式输出。
输入样例1:
00:00 61
输出样例1:
22:59
输入样例2:
23:59 1
输出样例2:
23:58
输入样例3:
06:00 630
输出样例3:
19:30

思路:
  本题也是一个简单题,先算出总分钟数,然后减去 N 分钟,若是一个负数,则不停加上一天的时间,直到变成整数。然后用总分钟数除以60,就得到小时数,对60取余,得到分钟数,再调整一下格式输出即可。

代码:

#include
int main(){
	int h, m, n;
	scanf("%d:%d %d",&h, &m, &n);
	m += h * 60;//计算总分钟数 
	m -= n;		//减去 n 分钟 
	while(m < 0){//若是负数,则不停加一天的时间,直到变成正数 
		m += 24 * 60;
	} 
	h = m / 60;//重新计算小时和分钟 
	m = m % 60;
	//调整格式输出 
	if(h < 10) printf("0%d:",h);
	else printf("%d:",h);
	if(m < 10) printf("0%d",m);
	else printf("%d",m);
	return 0;
}

第五题:扑克牌

任务描述:
东北地区流行一种扑克游戏“拖拉机”,每个玩家发牌3张(不包括大小王)。
假定扑克牌中用2-14(11-14点分别代表J、Q、K、A)表示每张牌的点数,用S、H、C、D代表不同花色。代表花色的字符实为表示花色的英文单词开头字母,意义如下:黑桃(Spade)、红桃(Heart)、梅花(Club)、方块(Diamond)。
给你三张扑克牌(已去除大小王),例如:5S 6H 12C(黑桃5、红桃6、梅花Q)。请编程输出这组扑克牌的牌型名称(按最大牌型)和代表此牌型的最大牌,牌型名称及输出信息详见下方文字说明。
三张扑克牌构成的所有牌型从大到小排列如下(豹子>同花顺>顺子>同花>对子>花牌):
(1)豹子(Leopard):三张牌点数一样,如5S 5H 5C。此组牌为“黑桃5、红桃5、方块5”,牌型为“豹子5”,对应的输出是:Leopard 5。
(2)同花顺(Flush straight):三张牌同花色且点数恰好相邻,如5S 7S 6S。此组牌为“黑桃5、黑桃7、黑桃6”,牌型理解为“同花顺7”,对应输出是:Flush straight 7。
(3)顺子(Straight):三张牌点数恰好相邻,但不同花色,如10H 11D 12C。牌型理解为“顺子Q”,对应输出是:Straight Q。
(4)同花(Same kind):三张牌花色相同,点数不全相同,如8H 5H 11H。牌型理解为“同花J”,对应的输出是:Same kind J。
(5)对子(Pair):花色不全相同,仅两张牌点数相同,如11H 14C 11D。牌型理解为“对子J”,对应的输出是:Pair J。
(6)花牌(General):花色不全相同,点数全不相同,如:5D 13C 8H。牌型理解为“花牌K”,对应的输出是:General K。如:5D 14C 8H。牌型理解为“花牌A”,对应的输出是:General A。
输入格式:
输入中包括多组测试数据,其中第一行是一个整数n(1<=n<=10),代表包含n组数据。
接下来的k行中,每一行是一组测试数据(三张扑克牌)。
每组测试数据是在一行中包括三张扑克牌,两张牌之间以一个空格分隔。每张牌由数字点数和花色字符构成,例如12D代表“方块Q”。
输出格式:
按顺序输出每组测试数据的牌型,每组数据的输出单独占一行。
输入样例1
6
5S 5H 5C
5S 7S 6S
10H 11D 12C
8H 5H 11H
11H 14C 11D
5D 13C 8H
输出样例1
Leopard 5
Flush straight 7
Straight Q
Same kind J
Pair J
General K
输入样例2
5
13H 13S 13C
2D 12S 2C
14H 10S 10D
11C 12D 10S
10C 12C 11C
输出样例2
Leopard K
Pair 2
Pair 10
Straight Q
Flush straight Q

思路:
  本题因为题目内容多,看似有点难,其实题意弄清楚后也很简单,牌型无非就那几种,写几个函数去判断即可,牌需要定义成结构体。总的来说就是按照手牌点数大小去排个序,然后判断最大牌型以及对应的点数即可。

代码:

#include
#include
typedef struct {//定义牌结构体
	int rank;	//点数 
	char color;	//花色 
} Card; 
int cmp(const void *a, const void *b){//按牌点数从小到大排序, 
	Card *m = (Card *) a;
	Card *n = (Card *) b;
	return m->rank - n->rank;
}
int isLeopard(Card hand[]){//豹子判断 
	return hand[0].rank==hand[1].rank&&hand[1].rank==hand[2].rank;
}
int isStraight(Card hand[]){//顺子判断 
	return hand[0].rank+1==hand[1].rank&&hand[1].rank+1==hand[2].rank;
} 
int isSamekind(Card hand[]){//同花判断 
	return hand[0].color==hand[1].color&&hand[1].color==hand[2].color;
}
int isFlushStraight(Card hand[]){//同花顺判断 
	return isStraight(hand) && isSamekind(hand);
}
int isPair(Card hand[]){//对子判断 
	return hand[0].rank==hand[1].rank||hand[1].rank==hand[2].rank;
} 
int main(){
	int n;
	scanf("%d", &n);
	while(n-- > 0){
		Card hand[3];
		scanf("%d%c %d%c %d%c",&hand[0].rank,&hand[0].color,
		&hand[1].rank,&hand[1].color,&hand[2].rank,&hand[2].color);
		qsort(hand, 3, sizeof(Card), cmp); 
		//先输出牌型,牌型只有一种,优先级从高到低判断 
		if(isLeopard(hand)){
			printf("Leopard "); 
		} else if(isFlushStraight(hand)){
			printf("Flush straight ");
		} else if(isStraight(hand)){
			printf("Straight ");
		} else if(isSamekind(hand)){
			printf("Same kind ");
		} else if(isPair(hand)){
			printf("Pair ");
		} else printf("General ");
		
		//最大牌型的点数 
        int lastRank = hand[2].rank;
        //若是对子,最大牌型的点数可以是前两个,所以对子的最大牌型点数不一定是最大点数 
        if(isPair(hand)) lastRank = hand[1].rank;
        //输出点数
		if(lastRank <= 10) printf("%d\n",lastRank);
		else if(lastRank == 11) printf("J\n");
		else if(lastRank == 12) printf("Q\n");
		else printf("K\n");
	}
	return 0;
} 

你可能感兴趣的:(c语言,算法)