您的位置:首页 > 其它

憨憨寒假训练(一)-- 结构体专题

2020-02-03 04:23 176 查看

❤心爱的大佬❤于百忙之中给我整理了一份结构体专题的试卷(●ˇ∀ˇ●)
满分:100,嗐,在大佬的无数提示下勉强及格…(;′⌒`)
上一篇是总结的的这类型的题的思路,这一篇总结一下此类型的题(ง •_•)ง

1.PAT (Basic Level) Practice 1041 考试座位号 (15分)

每个PAT考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试座位就座。但有些考生迟到了,试机已经结束,他们只能拿着领到的试机座位号码求助于你,从后台查出他们的考试座位号码。

输入格式:

输入第一行给出一个正整数 N(≤1000),随后 N 行,每行给出一个考生的信息:准考证号 试机座位号 考试座位号。其中准考证号由 16
位数字组成,座位从 1 到 N 编号。输入保证每个人的准考证号都不同,并且任何时候都不会把两个人分配到同一个座位上。
考生信息之后,给出一个正整数 M(≤N),随后一行中给出 M 个待查询的试机座位号码,以空格分隔。

输出格式:

对应每个需要查询的试机座位号码,在一行中输出对应考生的准考证号和考试座位号码,中间用 1 个空格分隔。

输入样例:

4
3310120150912233 2 4
3310120150912119 4 1
3310120150912126 1 3
3310120150912002 3 2
2
3 4

输出样例:

3310120150912002 2
3310120150912119 1

15分代码如下:(存入vector然后遍历)

#include<bits/stdc++.h>
using namespace std;
struct stu{
string id;
int x,y;
};
int main()
{
ios::sync_with_stdio(false);//取消cin和stdin的同步
cin.tie(0),cout.tie(0);
int n;
cin >> n;
vector<stu> v;
int stu1[n];
for(int i=0;i<n;i++){
stu t;
cin >> t.id >> t.x >> t.y;
v.push_back(t);
}
int m;
cin >> m;
for(int i = 0;i<m;i++){
int x;
cin >> x;
for(int j = 0;j<n;j++){
if(x==v[j].x){
cout << v[j].id << " " <<v[j].y << endl;
}
}
}
}

2.PAT (Basic Level) Practice 1038 统计同成绩学生 (20分)

本题要求读入 N 名学生的成绩,将获得某一给定分数的学生人数输出。

输入格式:

输入在第 1 行给出不超过1e5的正整数 N,即学生总人数。随后一行给出N名学生的百分制整数成绩,中间以空格分隔。最后一行给出要查询的分数个数 K(不超过 N 的正整数),随后是 K 个分数,中间以空格分隔。

输出格式:

在一行中按查询顺序给出得分等于指定分数的学生人数,中间以空格分隔,但行末不得有多余空格。

输入样例:

10
60 75 90 55 75 99 82 90 75 50
3 75 90 88

输出样例:

3 2 0

14分代码如下:(有部分测试数据TLE…)

#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n;
cin >> n;
vector<int> v;
for(int i = 0;i<n;i++){
int x;
cin >> x;
v.push_back(x);
}
int m;
cin >> m;
for(int i = 0;i<m;i++){
int y;
cin >> y;
int cnt = 0;
for(int j = 0;j<n;j++){
if(v[j]==y) cnt++;
}
printf("%d%s",cnt,i!=m-1?" ":"\n");
}
}

心爱大佬教的另外两种求解方法
第一种20分代码:(map解法)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;

int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
map<int,int> m;  //map的first是分数,second是考得该分数的学生个数
/*
map<typename1,typename2> m;
可以理解为
struct map{
typename1 first;   //key
typename2 second;  //value
};
可以根据key来查看value值
*/
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
int _;
cin >> _;
m[_]++;
}
int k;
cin >> k;
for (int i = 0; i < k; i++)
{
int _;
cin >> _;
cout << m[_] << (i!=k-1?" ":"\n");
}
return 0;
}

第二种20分代码:(hash【散列】解法)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 101;  //由于要有100分的下标,所以下标最大值应设为101,否则提交会有部分数据不对

int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int hash[maxn];     //记录0~100分每个分数出现的学生个数
memset(hash,0,sizeof(hash));
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
int _;
cin >> _;
hash[_]++;
}
int k;
cin >> k;
for (int i = 0; i < k; i++)
{
int _;
cin >> _;
cout << hash[_] << (i!=k-1?" ":"\n");
}
return 0;
}

3.PAT (Basic Level) Practice 1028 人口普查 (20分)

某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200 岁的老人,而今天是 2014 年 9 月 6 日,所以超过 200 岁的生日和未出生的生日都是不合理的,应该被过滤掉。

输入格式:

输入在第一行给出正整数 N,取值在(0,1e5 ​​ ];随后 N 行,每行给出 1 个人的姓名(由不超过 5个英文字母组成的字符串)、以及yyyy/mm/dd(即年/月/日)格式给出的生日。题目保证最年长和最年轻的人没有并列。

输出格式:

在一行中顺序输出有效生日的个数、最年长人和最年轻人的姓名,其间以空格分隔。

输入样例:

5
John 2001/05/12
Tom 1814/09/06
Ann 2121/01/30
James 1814/09/05
Steve 1967/11/20

输出样例:

3 Tom John

20分代码如下:
一开始只有19分(成功解锁一种新错法:段错误:您的程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起)
解释成这样容易让我怀疑是否因为判断年龄合理是不是写错了,但是真正的问题是如果合理人数是0时,不能输出多余的空格。。。

#include<bits/stdc++.h>
using namespace std;
struct people{
string name;
int yyyy,mm,dd;
};
bool cmp(people a,people b)
{
if(a.yyyy!=b.yyyy){
return a.yyyy < b.yyyy;
}else if(a.mm!=b.mm){
return a.mm < b.mm;
}else{
return a.dd < b.dd;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
vector<people> v;
int n;
cin >> n;
for(int i=0;i<n;i++){
people t;
char a;
cin >> t.name >>t.yyyy >>a>>t.mm>>a>>t.dd;
if(t.yyyy==2014&&t.mm<9||t.yyyy==2014&&t.mm==9&&t.dd<=6||t.yyyy==1814&&t.mm>9||t.yyyy==1814&&t.mm==9&&t.dd>=6||t.yyyy>1814&&t.yyyy<2014){
v.push_back(t);
continue;
}
}
sort(v.begin(),v.end(),cmp);
if(v.size()==0){
cout << v.size();
}else{
cout << v.size() <<" "<<v[0].name <<" "<<v[v.size()-1].name;
}
}

这题如果将生日写成int型,判断生日的合理性时会很麻烦,查找了别的大佬的博客,两种方案:1)将出生日期写成string接收;2)将int型生日的年份1000+月份100+日期。否则就要理清如何满足0-200岁。

4.PAT (Basic Level) Practice 1082 射击比赛 (20分)

本题目给出的射击比赛的规则非常简单,谁打的弹洞距离靶心最近,谁就是冠军;谁差得最远,谁就是菜鸟。本题给出一系列弹洞的平面坐标(x,y),请你编写程序找出冠军和菜鸟。我们假设靶心在原点(0,0)。

输入格式:

输入在第一行中给出一个正整数 N(≤ 10 000)。随后 N 行,每行按下列格式给出:ID x y

其中 ID 是运动员的编号(由 4 位数字组成);x 和 y 是其打出的弹洞的平面坐标(x,y),均为整数,且 0 ≤ |x|, |y| ≤ 100。题目保证每个运动员的编号不重复,且每人只打 1 枪。

输出格式:

输出冠军和菜鸟的编号,中间空 1 格。题目保证他们是唯一的。

输入样例:

3
0001 5 7
1020 -1 3
0233 0 -1

输出样例:

0233 0001

20代码如下:(vector+sort)

#include<bits/stdc++.h>
using namespace std;
struct people{
string id;
int x,y;
};
bool cmp(people a,people b){
return a.x*a.x+a.y*a.y < b.x*b.x+b.y*b.y;
}
int main()
{
int n;
cin >> n;
vector<people> v;
for(int i = 0;i<n;i++){
people t;
cin >> t.id >> t.x >>t.y;
v.push_back(t);
}
sort(v.begin(),v.end(),cmp);
cout << v[0].id <<" "<<v[v.size()-1].id;
}

5.PAT (Basic Level) Practice 1015 德才论 (25分)
原题链接

宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人。凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人。”现给出一批考生的德才分数,请根据司马光的理论给出录取排名。

输入格式:

输入第一行给出 3 个正整数,分别为:N(≤1e5​​ ),即考生总数;L(≥60),为录取最低分数线,即德分和才分均不低于 L 的考生才有资格被考虑录取;H(<100),为优先录取线——德分和才分均不低于此线的被定义为“才德全尽”,此类考生按德才总分从高到低排序;才分不到但德分到线的一类考生属于“德胜才”,也按总分排序,但排在第一类考生之后;德才分均低于H,但是德分不低于才分的考生属于“才德兼亡”但尚有“德胜才”者,按总分排序,但排在第二类考生之后;其他达到最低线 L 的考生也按总分排序,但排在第三类考生之后。
随后 N 行,每行给出一位考生的信息,包括:准考证号 德分 才分,其中准考证号为 8 位整数,德才分为区间 [0, 100] 内的整数。数字间以空格分隔。

输出格式:

输出第一行首先给出达到最低分数线的考生人数 M,随后 M行,每行按照输入格式输出一位考生的信息,考生按输入中说明的规则从高到低排序。当某类考生中有多人总分相同时,按其德分降序排列;若德分也并列,则按准考证号的升序输出。

输入样例:

14 60 80
10000001 64 90
10000002 90 60
10000011 85 80
10000003 85 80
10000004 80 85
10000005 82 77
10000006 83 76
10000007 90 78
10000008 75 79
10000009 59 90
10000010 88 45
10000012 80 100
10000013 90 99
10000014 66 60

输出样例:

12
10000013 90 99
10000012 80 100
10000003 85 80
10000011 85 80
10000004 80 85
10000007 90 78
10000006 83 76
10000005 82 77
10000002 90 60
10000014 66 60
10000008 75 79
10000001 64 90

嗐,我太菜了,这题没有写出来,于是0分。。。
心爱大佬的题解链接

大佬的思路:先对考生进行分类,然后按照总分从高到低进行分类,总分相同时按照得分降序排序,总分得分都相同时,按照准考证号升序输出,用到cin一定要取消cin和stdin的同步,否则TLE。。。

心爱大佬的25分代码如下:

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

struct student
{
int ID;   //准考证号
int de,cai,sum;   //德分和才分,总分
int level;  //考生类别
};

bool Cmp(student a,student b)
{
if(a.level != b.level)
{
return a.level < b.level;
}
else if(a.sum != b.sum)
{
return a.sum > b.sum;   //按照总分从高到低的顺序进行排序
}
else if(a.de != b.de)
{
return a.de > b.de;   //总分相同时,按照德分降序排列
}
else
{
return a.ID < b.ID;   //总分和德分都并列时,按准考证号的升序输出
}
}
int main()
{
ios::sync_with_stdio(false);
int N,L,H,M;
cin >> N >> L >> H;
M = N;
std::vector<student> v(N);
for(int i = 0; i < N; i++)
{
cin >> v[i].ID >> v[i].de >> v[i].cai;
v[i].sum=v[i].de+v[i].cai;
if(v[i].de<L ||v[i].cai<L)
{
M--;
v[i].level=5;
}
else
{
if(v[i].de>=H && v[i].cai>=H)
{
v[i].level = 1;   //level=1说明考生 德分和才分都达到了优先录取线
}
else if(v[i].de>=H && v[i].cai<H)
{
v[i].level = 2;   //level=2说明考生 德分胜才分,且德分达到了最优录取线,才分未达到最优录取线
}
else if(v[i].de>=v[i].cai)
{
v[i].level = 3;   //level=3说明考生 德分胜才分,但德分未达到最优录取线
}
else
{
v[i].level = 4;  //level=4说明考生 德分低于最优录取线,且德不胜才
}
}
}
sort(v.begin(),v.end(),Cmp);
cout << M << endl;
for(int i = 0; i < M; i++)
{
cout << v[i].ID << " " <<v[i].de << " " << v[i].cai << endl;
}
return 0;
}
  • 点赞 2
  • 收藏
  • 分享
  • 文章举报
绀香零八 发布了32 篇原创文章 · 获赞 10 · 访问量 945 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: