结构体练习

目录

A - 唱歌比赛

B - 旗鼓相当的对手 - 加强版 

C -  最厉害的学生 

 D - 不重复数字

std::ios::sync_with_stdio(false)的运用      

continue 的用法详解     

C++中"str.find(i) != str.end()"和"str.find(i) = str.end()"     

E - 培训

F - Zone Selection

G - 演唱会

H - BNA - PICK


A - 唱歌比赛

Description

n(n≤100) 名同学参加歌唱比赛,并接受 m(m≤20) 名评委的评分,评分范围是0 到 10 分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下 m−2 个评分的平均数。请问得分最高的同学分数是多少?评分保留2 位小数。

Input

第一行两个整数n,m。
接下来 n 行,每行各 m 个整数,表示得分。

Output

输出分数最高的同学的分数,保留两位小数。

Sample 1

InputcopyOutputcopy
7 6
4 7 2 6 10 7
0 5 0 10 3 10
2 6 8 4 3 6
6 3 6 7 5 8
5 9 3 3 8 1
5 9 9 3 2 0
5 8 0 4 1 10
6.00

代码 

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int n,m;
	cin>>n>>m;
	int a[105][25];
	double maxf=-1;
	while(n--){
		int maxa=-1,mina=11;
		int z=0;
		double f=0;
		for(int i=0;i<m;i++){
			cin>>a[n][i];
			maxa=max(a[n][i],maxa);
			mina=min(a[n][i],mina); //去掉最大最小评分
		}
		for(int i=0;i<m;i++) z+=a[n][i];
		z=z-maxa-mina;
		//cout<<z<<endl; 
		f=1.0*z/(m-2); //平均分
		//cout<<f<<endl;
		maxf=max(maxf,f);
	}
	printf("%.2lf\n",maxf);
	return 0;
}

B - 旗鼓相当的对手 - 加强版 

Description

现有 N(N≤1000) 名同学参加了期末考试,并且获得了每名同学的信息:姓名(不超过 8 个字符的字符串,没有空格)、语文、数学、英语成绩(均为不超过 150 的自然数)。如果某对学生 <i,j> 的每一科成绩的分差都不大于 5,且总分分差不大于 10,那么这对学生就是“旗鼓相当的对手”。现在我们想知道这些同学中,哪些是“旗鼓相当的对手”?请输出他们的姓名。

所有人的姓名是按照字典序给出的,输出时也应该按照字典序输出所有对手组合。也就是说,这对组合的第一个名字的字典序应该小于第二个;如果两个组合中第一个名字不一样,则第一个名字字典序小的先输出;如果两个组合的第一个名字一样但第二个名字不同,则第二个名字字典序小的先输出。

Input

第一行输入一个正整数 N,表示学生个数。

第二行开始,往下 N 行,对于每一行首先先输入一个字符串表示学生姓名,再输入三个自然数表示语文、数学、英语的成绩。均用空格相隔。

Output

输出若干行,每行两个以空格隔开的字符串,表示一组旗鼓相当的对手。注意题目描述中的输出格式。

Sample 1

InputcopyOutputcopy
3
fafa 90 90 90
lxl 95 85 90
senpai 100 80 91
fafa lxl
lxl senpai

Hint

数据保证,1≤N≤1000,姓名为长度不超过 88 的字符串,语文、数学、英语成绩均为不超过150 的自然数。

 代码

#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
struct student
{
	char  name[25];
	int yuwen;
	int shuxue;
	int yingyu;
	int sum;
	
}stu[1005];
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>stu[i].name>>stu[i].yuwen>>stu[i].shuxue>>stu[i].yingyu;
		stu[i].sum=stu[i].yuwen+stu[i].shuxue+stu[i].yingyu;
	}  
	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			if(abs(stu[i].sum-stu[j].sum)<=10){
				if(abs(stu[i].yuwen-stu[j].yuwen)<=5
				&&abs(stu[i].shuxue-stu[j].shuxue)<=5
				&&abs(stu[i].yingyu-stu[j].yingyu)<=5)
				cout<<stu[i].name<<" "<<stu[j].name<<endl;
			}
		}
	}
	return 0;
}

C -  最厉害的学生 

Description

现有 N 名同学参加了期末考试,并且获得了每名同学的信息:姓名(不超过 8 个字符的仅有英文小写字母的字符串)、语文、数学、英语成绩(均为不超过 150 的自然数)。总分最高的学生就是最厉害的,请输出最厉害的学生各项信息(姓名、各科成绩)。如果有多个总分相同的学生,输出靠前的那位。

Input

第一行输入一个正整数 N,表示学生个数。

第二行开始,往下 N 行,对于每一行首先先输入一个字符串表示学生姓名,再输入三个自然数表示语文、数学、英语的成绩。均用空格相隔。

Output

输出最厉害的学生。

Sample 1

InputcopyOutputcopy
3
senpai 114 51 4
lxl 114 10 23
fafa 51 42 60
senpai 114 51 4

Hint

数据保证,1≤N≤1000,姓名为长度不超过 8 的字符串,语文、数学、英语成绩均为不超过 150 的自然数。

代码 

#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
struct student
{
	char  name[25];
	int yuwen;
	int shuxue;
	int yingyu;
	int sum;
	
}stu[1005];
int main()
{
	int n;
	cin>>n;
	int maxsum=-1;
	for(int i=0;i<n;i++){
		cin>>stu[i].name>>stu[i].yuwen>>stu[i].shuxue>>stu[i].yingyu;
		stu[i].sum=stu[i].yuwen+stu[i].shuxue+stu[i].yingyu;
	    maxsum=max(maxsum,stu[i].sum);
	} 
	for(int i=0;i<n;i++){
		if(stu[i].sum==maxsum){
			cout<<stu[i].name<<" "<<stu[i].yuwen<<" "<<stu[i].shuxue<<" "<<stu[i].yingyu<<endl;
		    break;
		}
	}
	return 0;
}

 D - 不重复数字

 

Description

给定 n 个数,要求把其中重复的去掉,只保留第一次出现的数。

Input

本题有多组数据。

第一行一个整数 T,表示数据组数。

对于每组数据:

第一行一个整数 n。

第二行 n 个数,表示给定的数。

Output

对于每组数据,输出一行,为去重后剩下的数,两个数之间用一个空格隔开。

Sample 1

InputcopyOutputcopy
2
11
1 2 18 3 3 19 2 3 6 5 4
6
1 2 3 4 5 6
1 2 18 3 19 6 5 4
1 2 3 4 5 6

Hint

对于 30% 的数据,n≤100,给出的数 ∈[0,100]。

对于 60% 的数据,n≤10^4,给出的数∈[0,10^4]。

对于 100% 的数据,1≤T≤50,1≤n≤5×10^4,给出的数在 32 位有符号整数范围内。

代码 

#include<set>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
 
int main()
{
    ios::sync_with_stdio(false);
    //c++中cin,cout效率较低,而这段语句可节省时间
    int t; cin >>t;
    while (t--){
         int n; cin >> n;
         vector<int> ans;
         set<int> s;
         for (int i = 1 ; i <= n ; i++){
            int x; cin >> x;
            if (s.find(x) != s.end()) continue; //如果找到就返回,不执行下面语句
            ans.push_back(x);
            s.insert(x);
         }
         for (auto g : ans) cout << g << " ";
         cout << endl;
    }
    return 0;
}
std::ios::sync_with_stdio(false)的运用      
continue 的用法详解     
C++中"str.find(i) != str.end()"和"str.find(i) = str.end()"     

E - 培训

Description

某培训机构的学员有如下信息:

  • 姓名(字符串)
  • 年龄(周岁,整数)
  • 去年 NOIP 成绩(整数,且保证是 55 的倍数)

经过为期一年的培训,所有同学的成绩都有所提高,提升了 20%(当然 NOIP 满分是 600 分,不能超过这个得分)。

输入学员信息,请设计一个结构体储存这些学生信息,并设计一个函数模拟培训过程,其参数是这样的结构体类型,返回同样的结构体类型,并输出学员信息。

Input

第一行输入一个正整数 n,表示学员个数。

第二行开始往下 n 行。每行首先是一个字符串表示学员姓名,再是一个整数表示学员年龄,再是一个整数为去年 NOIP 成绩。

Output

输出 n 行,每行首先输出一个字符串表示学生姓名,再往后两个整数,表示经过一年的培训后学员的年龄和他们今年的 NOIP 成绩。以空格隔开。

Sample 1

InputcopyOutputcopy
3
kkksc03 24 0
chen_zhe 14 400
nzhtl1477 18 590
kkksc03 25 0
chen_zhe 15 480
nzhtl1477 19 600

Hint

数据保证,1≤n≤5。年龄为0∼100(含 0 与 100)的整数。成绩为 0∼600(含 0 与600)的 5 的整倍数。

代码 


#include<iostream>
#include<algorithm>
using namespace std;
struct student
{
	char  name[25];
	int age;
	int noipused;
	int noipnow;
	
}stu[8];
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>stu[i].name>>stu[i].age>>stu[i].noipused;
		stu[i].age++; //过一年长一岁
		stu[i].noipnow=stu[i].noipused*1.2;  
	    if(stu[i].noipnow>600) stu[i].noipnow=600;  //每个人成绩提高
	} 
	for(int i=0;i<n;i++){
		cout<<stu[i].name<<" "<<stu[i].age<<" "<<stu[i].noipnow<<endl;
		
	}
	return 0;
}

F - Zone Selection

Description

在第五人格巅峰七阶及以上的排位赛中,需要进行区域选择。我们将在本题中形式化、推广化的解决区域选择问题。

在地图中,共有 n 台密码机,第 i 台密码机的坐标为 (xi​,yi​)。在推广化的游戏中,有 k 名求生者。每名求生者可以选择一台密码机作为其出生点,我们称被选择的密码机为 出生密码机

监管者共有 T 个出生点可供选择。第 i 个可能的出生点坐标为 (xi​,yi​)。此时,由于“封禁”天赋的存在,离监管者最远的密码机将不能被破译。

如果多台密码机与监管者的距离相同且最远,“封禁”天赋将会封禁这几台密码机中标号最小的那一台。

请问在该 T 个出生点中,有多少出生点,可以使某一台 出生密码机 被封禁。

请注意:坐标点 (x1​,y1​) 与坐标点 (x2​,y2​) 之间的距离为 2+(x1​−x2​)^2+(y1​−y2​)^2​。

Input

输入共 n+T+k+1 行。

输入的第一行为三个整数n,k,T。

接下来 n 行,每行两个整数 xi​,yi​,表示一台密码机的坐标。

接下来 k 行,每行两个整数 xi​,yi​,表示一名求生者选择出生密码机的坐标,保证该坐标在上面出现过。

接下来 T 行,每行两个整数 xi​,yi​,表示监管者的一个出生点。

Output

输出一行一个整数,为答案。

Sample 1

InputcopyOutputcopy
4 2 2
-1 0
0 -1
2 0
0 2
-1 0
0 2
3 0
0 0
1

Hint

【样例 #1 解释】

显然,第一台密码机和第四台密码机为出生密码机

第一位监管者与位置在(−1,0) 的第一台密码机距离最远,为 4。因此,第一台密码机被封禁。

第二位监管者与位置在(2,0),(0,2) 的第三、四台密码机距离相同且最远,为 2。根据上面提到的规则,第三台密码机被封禁。

被封禁的出生密码机为 1 台。

【数据规模与约定】

对前 10% 的数据,保证n=k=1。

对前 20% 的数据,保证 n,k,t≤10。

对另外 20% 的数据,保证密码机与出生点的坐标中的 x 均为 0。

对另外 10% 的数据,保证 n=k。

对另外 10% 的数据,保证 T=1。

对于 100% 的数据范围 1≤k≤n≤10^3,1≤T≤10^3,1≤∣xi​∣,∣yi​∣≤10^3。

思路 

记录各密码机,标记求生者选择的,判断被封禁的是否为被标记的 

 代码

#include<bits/stdc++.h>

using namespace std;

long long n, k, t, ans = 0;
struct point {
    int x, y;
    bool mark;
} a[1005];

double dist(int i, int j, int k1, int l) {
    return sqrt(((i - k1) * (i - k1) + (j - l) * (j - l)) * 1.0);
} //距离

int main() {
    cin >> n >> k >> t;
    for (int i = 1; i <= n; i++) 
	cin >> a[i].x >> a[i].y; 密码机的坐标
	
    for (int i = 1; i <= k; i++) {
        int x, y;
        cin >> x >> y;
        for (int j = 1; j <= n; j++) {
            if (x == a[j].x && y == a[j].y) {
                a[j].mark = true;求生者选择出生密码机的坐标
                break;
            }
        }
    }
    for (int i = 1; i <= t; i++) {
        int x, y;
        cin >> x >> y;
        double max_d = -1;
        int f = 0;
        for (int j = 1; j <= n; j++) {
            if (dist(x, y, a[j].x, a[j].y) > max_d) {
                max_d = dist(x, y, a[j].x, a[j].y);
                f = a[j].mark;出生密码机被封禁
            }
        }
        if (f) ans++; //如果是求生者选择的出生密码机就记录
    }
    cout << ans;
    return 0;
}

G - 演唱会

Description

一个特殊的节日,zyl 举办了一场演唱会,他想要规划一下演唱会的曲目。

根据同学的要求,他要从 n 首歌(编号 1∼n)中选出 m 首加入演唱会歌单。

选择的规则很简单,班上有 a 名学生(不包括 zyl),学号为 1∼a。zyl 会按照学号统计每位同学从每首歌中得到的快乐值,记为 hi,j​。一首歌的「欢乐度」是它所给予其他所有同学的「快乐值」总和。

巧妙的是,由于歌曲风格迥异,同一个学生一定会从不同的歌中会收获不同的快乐值,且不会有任何两首歌的欢乐度相同

zyl 选出欢乐度最高的 m 首歌,并将它们按欢乐度从大到小排好序。

但 zyl 注意到了她的快乐值…

无论如何,zyl 一定会把她最喜欢的歌放进歌单(她获得快乐值最高的歌即为她最喜欢的歌)!
如果她最喜欢的歌之前已经在歌单中,那么 zyl 会把这首歌提到歌单的第一个位置(即,仅将该歌曲的位置变为第一位,其余歌曲的相对位置不变);但如果不在,zyl 则会把已经选择好的歌单里的最后一首歌给删掉。然后把她最喜欢的曲目放在歌单的最后。

现在 zyl 将统计的快乐值数据和她的学号交给你,请你帮他列出演唱会的歌单。

Input

输入共 a+1 行。

第一行共四个整数 n,m,a,b,分别代表待选的歌的数量,需要选出的歌的数量,班上的人数,她的学号。
接下来 a 行,每行 n 个整数,第 i+1 行第 j 个数代表学号为 i 的学生从第 j 首歌收获的快乐值 hi,j​。

Output

输出共一行用空格隔开的 m 个整数,依次代表演唱会的歌单上的歌的编号。

Sample 1

InputcopyOutputcopy
4 2 3 2
2 4 3 1
1 2 3 4
2 3 4 1
3 4

Hint

样例 1 解释

按照欢乐度排序后靠前的两道是 3,2,但由于她最喜欢的歌是 4,不在歌单里,于是将 2 从歌单里删除,之后将 4 放在最后。最后的歌单为 3,4。

数据规模与约定

对于 100% 的数据,1≤m≤n≤10^5,1≤b≤a≤100。0≤ℎ,0≤hi,j​≤106。

测试点编号nmahi,j​
1∼2≤5=1≤5≤10000
3∼4≤1000=n≤100≤10000
5∼6≤1000≤1000=1≤10000
7∼9≤1000≤1000≤100≤10000
10≤10^5≤10^5≤100≤10^6

代码 

#include<bits/stdc++.h>
using namespace std;
struct song{
	int id;//编号 
	int k;//快乐值 
}h[100005];
bool cmp(song a,song b){
	return a.k>b.k;//排序 
}
int maxn,maxid;
int n,a,b,m;
int main(){
	cin >> n >> m >> a >> b;
	for(int i =1;i<=a;i++ ){
		for(int j = 1;j<=n;j++){
			int x;
			scanf("%d",&x);
			if(i==b){
				if(x>maxn)maxn = x,maxid = j;//zyl最喜欢的歌 
			}
			h[j].k+=x,h[j].id = j;//歌的快乐值及编号
		}
	} 
	sort(h+1,h+n+1,cmp);//快乐值排序
	bool f=0;
	for(int i = 1;i<=m;i++)if(h[i].id==maxid)f=1;
	if(f==1){ //最喜欢歌在其中 
		cout <<maxid<<" ";
		for(int i =1;i<=m;i++)if(h[i].id!=maxid)cout <<h[i].id<<" ";
	}
	else{//不再其中 
		for(int i = 1;i<m;i++)cout <<h[i].id<<" ";
		cout <<maxid;
	}
	return 0;
}

H - BNA - PICK

Description

在第五人格职业联赛的每一场对局中,需要进行 Ban-Pick 流程。Ban 即角色禁用,Pick 即角色选用。

如试题 Winner 所述,游戏分为 求生者(SurvivorSurvivor) 与 监管者(HunterHunter) 两个阵营。求生者阵营 共有 n 名角色,监管者阵营 共有 m 名角色。

在某局比赛中,监管者 可以 ban(禁用) 掉 求生者阵营 5 名角色,求生者 可以 ban(禁用) 掉 监管者阵营 2 名角色。

每个角色,无论其属于求生者阵营还是监管者阵营,均可以使用 熟练度 来量化该阵营选手选择该角色的优先程度。选手一定会优先选择 熟练度 更高的角色进行游戏。

基于这样的考量,监管者选手 在进行 Ban 流程时,往往会选择 ban(禁用) 掉 求生者阵营熟练度最高 的若干名 求生者角色。同样,求生者选手 在进行 Ban 流程时,往往会选择 ban(禁用) 掉 监管者阵营熟练度最高 的若干名 监管者角色

在 Ban 流程完成后,需要执行 Pick 流程。

如试题 Winner 所述,求生者选手 需要从 求生者阵营 中选择 4 名不同的角色,监管者选手 需要从 监管者阵营 中选择 1 名角色。

现在告诉你所有角色的名字、阵营与选手对其熟练度,请你给出双方阵营 Pick 的角色名字。

Input

输入共 1n+m+1 行。

输入的第一行为两个整数 n,m,分别代表求生者阵营角色数和监管者阵营角色数。

接下来n+m 行,首先为一个仅由英文字母组成的字符串,代表该角色的姓名;接下来为一个大写字符 H 或 S,若为 H,则代表该角色为监管者阵营,若为 S,则代表该角色为求生者阵营;接下来一个正整数,代表该阵营选手对该角色的熟练度。上述字符串、大写字符、正整数之间由一个空格分隔。

Output

输出共 5 行。

输出的第一行为监管者阵营选择角色的角色名。

输出的第二到五行为求生者阵营选择角色的角色名,按照熟练度从高到低排列。

Sample 1

InputcopyOutputcopy
9 3
Amily S 1
Lydia S 2
Lisa S 4
Beck H 1
Freddie S 5
Cliche S 6
Aesop S 7
Eli S 8
Norton S 9
Tiletower H 3
Yidhra H 2
Emma S 3
Beck
Lisa
Emma
Lydia
Amily

Hint

输入输出样例 1 解释

求生者阵营角色:Amily,Lydia,Lisa,Freddie,Cliche,Aesop,Eli,Norton,Emma

监管者阵营角色:Beck,Tiletower,Yidhra

监管者选手将 ban 掉求生者阵营中角色 Norton,Eli,Aesop,Cliche,Freddie

求生者选手将 ban 掉监管者阵营中角色 Tiletower,Yidhra

思路 

 监管者 可以 ban(禁用) 掉 求生者阵营 5 名角色,求生者 可以 ban(禁用) 掉 监管者阵营 2 名角色,求生者选手 需要从 求生者阵营 中选择 4 名不同的角色,监管者选手 需要从 监管者阵营 中选择 1 名角色,被ban(禁用) 或被选都是 熟练度最高的。

所以,直接输出熟练度排名为 监管者阵营·3和求生者阵营·6-9 就可以

 代码

#include<bits/stdc++.h>
using namespace std;
struct node {
	string name; //求生者与监管者名
	long long val; //熟练度
} s[100005], h[100005]; 
int cmp(node x, node y) {
	return x.val > y.val;
}  //熟练度排序
int n,m;
signed main(){
	int cntH = 0, cntS = 0;
    cin >> n >> m;
    for (int i = 1; i <= n + m; ++i) {
	     string name, v;
	     long long val;
	     cin >> name >> v >> val;
	     if (v == "H") {  //判断阵营为监管者
		    ++cntH;
		    h[cntH].name = name;
	      	h[cntH].val = val;
	    } 
		else {  //求生者阵营
		    ++cntS;
		    s[cntS].name = name;
		    s[cntS].val = val;
	    }
    }
	sort(s + 1, s + cntS + 1, cmp);
    sort(h + 1, h + cntH + 1, cmp);

    cout << h[3].name << endl;
    for (int i = 6; i <= 9; ++i) {
	     cout << s[i].name << endl;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值