结构体6~10(2356. 成绩排序、1740. 统计每个数出现的次数、1940. 混合牛奶、1314. 仰卧起坐成绩统计、1953. 新生舞会、1346. 等比例缩放照片)

题单地址:题单中心-东方博宜OJ

1372. 活动选择

在贪心专题有详细讲解:贪心1~7-CSDN博客


2356. 成绩排序

问题描述(补充一道我觉得有代表性的题目)

【具体要求】

虽然现在学校已经不允许将学生每次的考试成绩公布,但是尽职尽责的班主任小青老师还是会私下将学生们的成绩排序,看看哪些学生进步了,哪些学生有所退步,针对退步的学生想一些提升方案。

现在请你通过编程来帮助小青老师实现全班 n 位同学成绩的排名。排名规则为总分从高到低排序,当出现总成绩相同时,根据语文成绩从高到低排序;当总成绩相同且语文成绩也相同时按照输入的先后顺序排序。

输入

输入共 n+1 行,第一行输入一个正整数 n(1 < n < 100)表示全班学生数量;

第 2~n+1 行,每行分别是学生姓名 m(1 < m < 20)、语文成绩、数学成绩、英语成绩,中间用空格隔开,各科成绩满分 100 分。

输出

输出共 n 行,根据题目要求的排序规则输出,每行分别为学生姓名、总成绩、语文成绩。

样例

输入

3

Jack 93 97 96

Rose 96 98 94

Lanbao 94 98 94

输出

Rose 288 96

Lanbao 286 94

Jack 286 93

解析:要注意排名成绩的优先级,这大大增加了cmp的编写难度。

#include <bits/stdc++.h>
using namespace std;

struct node{
	string name;
	int yu, shu, yin, sum, k;
}a[10005];

bool cmp(node a, node b){
	if(a.sum == b.sum && a.yu == b.yu)return a.k < b.k;
	else if(a.sum == b.sum)return a.yu > b.yu;
	else return a.sum > b.sum;
}

int main() {
	int n;
	cin >> n;
	for(int i = 0; i < n; i++){
		cin >> a[i].name >> a[i].yu >> a[i].shu >> a[i].yin;
		a[i].sum = a[i].yu + a[i].shu + a[i].yin;
		a[i].k = i;
	}
	sort(a, a+n, cmp);
	for(int i = 0; i < n; i++){
		cout << a[i].name << ' ' << a[i].sum << ' ' << a[i].yu << endl;
	}
	return 0;	
} 

1740. 统计每个数出现的次数

问题描述

从键盘读入 n 个数( n ≤ 1000 ),统计每个数出现的次数,从小到大输出每个出现过的数,及每个数出现的次数。

比如:假设从键盘读入 6 个数,分别是:1 6 8 1 2 6,那么输出如下:

1 2
2 1
6 2
8 1

输出含义为:1 出现了 2 次, 2 出现了 1 次, 6 出现了 2 次, 8 出现了 1 次。

输入

第 1 行有一个整数 n (n ≤ 1000)

第 2 行有 n 个整数,数字之间用空格隔开,这 n 个数都是 int 范围内的数

输出

输出若干行,每行 2 个数,第 1 个数是出现过的数,第 2 个数是该数出现的次数,要求从小到大输出每个数及每个数出现的次数。

样例

输入

10

2 8 1 2 3 3 6 1 1 1000

输出

1 3

2 2

3 2

6 1

8 1

1000 1

 解析:使用map记录每个数组的投票结果,在复制到结构体数组中排序。

#include <bits/stdc++.h>
using namespace std;

struct node{
	int name;
	int k;
}a[10005];

bool cmp(node a, node b){
	return a.name < b.name;
}

int main() {
	int n, k = 0;
	int s;
	cin >> n;
	map<int, int> m;
	for(int i = 0; i < n; i++){
		cin >> s;
		if(m.find(s) == m.end()){
			m[s] = 1;
			a[k++].name = s;
		}
		else m[s]++;
	}
	for(int i = 0; i < k; i++){
		a[i].k = m[a[i].name];
	}
	sort(a, a+k, cmp);
	for(int i = 0; i < k; i++){
		cout << a[i].name << ' ' << a[i].k << endl;
	}
	return 0;	
} 

1940. 混合牛奶 Mixing Milk

问题描述

由于乳制品产业利润很低,所以降低原材料(牛奶)价格就变得十分重要。帮助 Marry 乳业找到最优的牛奶采购方案。

Marry 乳业从一些奶农手中采购牛奶,并且每一位奶农为乳制品加工企业提供的价格是不同的。此外,就像每头奶牛每天只能挤出固定数量的奶,每位奶农每天能提供的牛奶数量是一定的。每天 Marry 乳业可以从奶农手中采购到小于或者等于奶农最大产量的整数数量的牛奶。

给出 Marry 乳业每天对牛奶的需求量,还有每位奶农提供的牛奶单价和产量。计算采购足够数量的牛奶所需的最小花费。

注:每天所有奶农的总产量大于 Marry 乳业的需求量。

输入

第一行二个整数 n,m,表示需要牛奶的总量,和提供牛奶的农民个数。
接下来 m 行,每行两个整数 pi​,ai​,表示第 i 个农民牛奶的单价,和农民 i 一天最多能卖出的牛奶量。

输出

单独的一行包含单独的一个整数,表示 Marry 的牛奶制造公司拿到所需的牛奶所要的最小费用。

样例

输入

100 5

5 20

9 40

3 10

8 80

6 30

输出

630

解析:难度不大,主要用到结构体数组存储数据,贪心枚举即可。

#include <bits/stdc++.h>
using namespace std;

struct node{
	int w, k;
}a[1000005];

bool cmp(node a, node b){
	return a.w < b.w;
}

int main(){
	int n, m, sum = 0;
	cin >> n >> m;
	for(int i = 1; i <= m; i++){
		cin >> a[i].w >> a[i].k;
	}
	sort(a + 1, a + 1 + m, cmp);
	for(int i = 1; i <= m; i++){
		if(n - a[i].k <= 0){
			sum += a[i].w * n;
			break;
		} 
		else if(n - a[i].k > 0){
			sum += a[i].k * a[i].w;
			n -= a[i].k;
		}
	}
	cout << sum;
	return 0;
}

1314. 仰卧起坐成绩统计

问题描述

四年级二班女同学在体育课上进行了一轮仰卧起坐测试。成绩计算表如下。

一分钟内做仰卧起坐的个数  成绩
   <20个                                  F
  20~29个                               E
  30~39个                               D
  40~49个                               C
  50~59个                               B
  >=60个                                 A

请从键盘读入 n 位同学的在一分钟内做仰卧起坐的数量,计算出每个成绩区间的人数,按照人数降序排序,如果有多个成绩区间人数一样多,那么先输出成绩较好的区间。

输入

第一行是一个整数 n 代表同学的人数( n ≤ 100 );

第二行是 n 个同学一分钟完成仰卧起坐的数量。

输出

输出 6 行为 6 个成绩区间的人数,每行按照“成绩:人数”的格式输出,按照人数降序输出。

样例

输入

10

19 18 17 20 21 28 30 45 48 51

输出

E:3

F:3

C:2

B:1

D:1

A:0

解析:需要使用map记录每个成绩的人数,再复制到结构体数组中排序即可。

#include <bits/stdc++.h>
using namespace std;

struct node{
	string name;
	int k;
}a[10005];

bool cmp(node a, node b){
	if(a.k == b.k)return a.name < b.name;
	return a.k > b.k;
}

int main() {
	int n, k = 0;
	int s;
	char c;
	cin >> n;
	map<char, int> m;
	for(int i = 0; i < n; i++){
		cin >> s;
		if(s >= 60)c = 'A';
		else if(s >= 50)c = 'B';
		else if(s >= 40)c = 'C';
		else if(s >= 30)c = 'D';
		else if(s >= 20)c = 'E';
		else c = 'F';
		if(m.find(c) == m.end()){
			m[c] = 1;
		}
		else m[c]++;
	}
	for(char i = 'F'; i >= 'A'; i--){
		a[int(i-'A')].name = i;
		a[int(i-'A')].k = m[i];
	}
	sort(a, a+6, cmp);
	for(int i = 0; i < 6; i++){
		cout << a[i].name << ':' << a[i].k << endl;
	}
	return 0;	
}

1953. 新生舞会

问题描述

新生舞会开始了。

n 名新生每人有三个属性:姓名、学号、性别。其中,姓名用长度不超过 20 的仅由大小写字母构成的字符串表示,学号用长度不超过 10 的仅由数字构成的字符串表示,性别用一个大写字符 F 或 M 表示。任意两人的姓名、学号均互不相同。换言之,每个人可被其姓名或学号唯一确定。

给出 m 对两人的信息(姓名或学号),判断他们是否能共舞。两人能共舞的充要条件为两人性别相异。

输入

第一行一个整数 n(2 ≤ n ≤ 1000),表示学生人数。接下来的 n 行每行依次包含一名新生的姓名、学号、性别,分别用一个空格隔开。

之后的一行是一个整数 m (1 ≤ m ≤ 1000),表示询问的数目。

接着的 m 行每行包含两个信息(姓名或学号),保证两个信息不属于同一人,中间用一个空格隔开。

输出

对于每个询问输出一行,如果两人可以共舞,输出一个大写字母 Y,否则输出一个大写字母 N。

样例

输入

4

John 10 M

Jack 11 M

Kate 20 F

Jim 21 M

3

John 11

20 Jack

Jim Jack

输出

N

Y

N

解析:结构体数组存储信息,在一一匹配即可。

#include <bits/stdc++.h>
using namespace std;

struct node{
	string name, k;
	char c;
}a[10005];

int main() {
	int n, m;
	cin >> n;
	for(int i = 0; i < n; i++){
		cin >> a[i].name >> a[i].k >> a[i].c;
	}
	cin >> m;
	string s1, s2;
	for(int i = 0; i < m; i++){
		char ans1, ans2;
		cin >> s1 >> s2;
		if(s1[0] >= '0' && s1[0] <= '9'){
			for(int i = 0; i < n; i++){
				if(a[i].k == s1)ans1 = a[i].c;
			}
		}
		else{
			for(int i = 0; i < n; i++){
				if(a[i].name == s1)ans1 = a[i].c;
			}
		}
		if(s2[0] >= '0' && s2[0] <= '9'){
			for(int i = 0; i < n; i++){
				if(a[i].k == s2)ans2 = a[i].c;
			}
		}
		else{
			for(int i = 0; i < n; i++){
				if(a[i].name == s2)ans2 = a[i].c;
			}
		}
		if(ans1 == ans2)cout << 'N' << endl;
		else cout << 'Y' << endl;
	}
	return 0;	
} 

1346. 等比例缩放照片

问题描述(我觉得较好的题目也加入进来)

如图所示的一张照片(图①),可以把它的宽度或者高度减小从而减少照片的尺寸(如图②、③、④)。但只有等比例缩放的情况下照片才是最好看的,如图④;图②照片被压扁,图③照片被拉长。
给定图片的原始尺寸以及n组要压缩的尺寸,请问哪组压缩后的数据的宽高比最接近原始数据?如果有多组压缩尺寸的宽高比都是一样的且都是最接近原始数据的,那么输出压缩后面积最小的那组数据。

输入

第1行,2个整数x和y,代表图片的原始尺寸的宽和高

第2行,一个整数n,代表接下来有n组压缩后的尺寸(n <= 100)

接下来n行,每行2个数,代表n组压缩后的宽和高(确保输入的宽 >= 高)(本题所有照片的宽高均在1~10000之间)

输出

宽高比和原始图片最接近的宽高数据,如果有多组这样的数,输出面积最小的那组(不存在多组宽高比和原始数据一样接近且面积又一样的数据)

样例

输入

10 4

4

20 4

60 10

15 9

10 6

输出

10 6

解析:这道题目考验枚举的思路,使用排序解决不太好定义排序规则,使用枚举打擂台的方式就直观许多。

#include <bits/stdc++.h>
using namespace std;

struct node{
	int x, y, s;
	double bi;
}a[105];

bool cmp(node a, node b){
	if(a.bi > b.bi)return 0;
	else if(a.bi == b.bi && a.s > b.s)return 0;
}

int main() {
	int n, h, w, k, l; 
	double m, minn = 100000;
	cin >> w >> h >> n;
	m = w * 1.0 / h;
	for(int i = 0; i < n; i++){
		cin >> a[i].x >> a[i].y;
		a[i].bi = a[i].x * 1.0 / a[i].y;
		a[i].s = a[i].x * a[i].y;
	}
	for(int i = 0; i <= n; i++){
		if(abs(a[i].bi - m) < (minn - m)){
			minn = a[i].bi;
			k = i;
			l = a[i].s;
		}
		if(minn == a[i].bi){
			if(a[i].s < l){
				minn = a[i].bi;
				k = i;
				l = a[i].s;
			}
		}
	}
	cout << a[k].x << " " << a[k].y;
	return 0;	
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值