名人堂与代金券
对于在中国大学MOOC(http://www.icourse163.org/ )学习“数据结构”课程的学生,想要获得一张合格证书,总评成绩必须达到 60 分及以上,并且有另加福利:总评分在 [G, 100] 区间内者,可以得到 50 元 PAT 代金券;在 [60, G) 区间内者,可以得到 20 元PAT代金券。全国考点通用,一年有效。同时任课老师还会把总评成绩前 K 名的学生列入课程“名人堂”。本题就请你编写程序,帮助老师列出名人堂的学生,并统计一共发出了面值多少元的 PAT 代金券。
输入格式:
输入在第一行给出 3 个整数,分别是 N(不超过 10 000 的正整数,为学生总数)、G(在 (60,100) 区间内的整数,为题面中描述的代金券等级分界线)、K(不超过 100 且不超过 N 的正整数,为进入名人堂的最低名次)。接下来 N 行,每行给出一位学生的账号(长度不超过15位、不带空格的字符串)和总评成绩(区间 [0, 100] 内的整数),其间以空格分隔。题目保证没有重复的账号。
输出格式:
首先在一行中输出发出的 PAT 代金券的总面值。然后按总评成绩非升序输出进入名人堂的学生的名次、账号和成绩,其间以 1 个空格分隔。需要注意的是:成绩相同的学生享有并列的排名,排名并列时,按账号的字母序升序输出。
输入样例:
10 80 5
cy@zju.edu.cn 78
cy@pat-edu.com 87
1001@qq.com 65
uh-oh@163.com 96
test@126.com 39
anyone@qq.com 87
zoe@mit.edu 80
jack@ucla.edu 88
bob@cmu.edu 80
ken@163.com 70
输出样例:
360
1 uh-oh@163.com 96
2 jack@ucla.edu 88
3 anyone@qq.com 87
3 cy@pat-edu.com 87
5 bob@cmu.edu 80
5 zoe@mit.edu 80
这题是一个比较简单的结构体排序的问题
定义一个结构体student,写入他的数据,按照题目的要求,成绩高的往前排,如果成绩相同,就按照账号的字典序来排序
所以我们就得把sort里面的cmp写一下
bool cmp(student b,student c){
if(b.cz!=c.cz) return b.cz>c.cz;
else return b.xh<c.xh;
}
再看一眼,这题的输出还是有讲究的
它的排名我们要怎么输出出来
首先,我们定义一个记录排名的整数p,初始化为1;
然后每次出现相同的数字时,p都不会变,但在下一个不相同的数据里面,p会加上前面相同的人的个数,那我们再定义一个xt数据来记录相同的数据的数量,初始化为0,如果前后两个数据相同,xt++;不相同的化就是p++,p+=xt;加完xt后,要记得对xt进行初始化再使用
代码如下
#include <bits/stdc++.h>
using namespace std;
struct student{
int cz;
string xh;
int qian=0;
int paim=0;
}a[100005];
bool cmp(student b,student c){
if(b.cz!=c.cz) return b.cz>c.cz;
else return b.xh<c.xh;
}
int main(){
int n,g,k;
cin>>n>>g>>k;
int sum=0;
for(int i=0 ; i<n ; i++ ){
cin>>a[i].xh>>a[i].cz;
if(a[i].cz>=60&&a[i].cz<g) a[i].qian=20;
else if(a[i].cz>=g&&a[i].cz<=100) a[i].qian=50;
sum+=a[i].qian;
}
cout<<sum<<endl;
sort(a,a+n,cmp);
while(a[k].cz==a[k-1].cz){//计算多少人要输出
k++;
}
int p=1;
int xt=0;
for(int i=0;i<k;i++){
cout<<p<<' '<<a[i].xh<<' '<<a[i].cz<<endl;
if(a[i+1].cz!=a[i].cz){
p+=xt;
p++;
xt=0;//不要忘记重置xt的个数
}
else xt++;
}
return 0;
}
排座位
布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。
输入格式:
输入第一行给出3个正整数:N
(≤100),即前来参宴的宾客总人数,则这些人从1到N
编号;M
为已知两两宾客之间的关系数;K
为查询的条数。随后M
行,每行给出一对宾客之间的关系,格式为:宾客1 宾客2 关系
,其中关系
为1表示是朋友,-1表示是死对头。注意两个人不可能既是朋友又是敌人。最后K
行,每行给出一对需要查询的宾客编号。
这里假设朋友的朋友也是朋友。但敌人的敌人并不一定就是朋友,朋友的敌人也不一定是敌人。只有单纯直接的敌对关系才是绝对不能同席的。
输出格式:
对每个查询输出一行结果:如果两位宾客之间是朋友,且没有敌对关系,则输出No problem
;如果他们之间并不是朋友,但也不敌对,则输出OK
;如果他们之间有敌对,然而也有共同的朋友,则输出OK but...
;如果他们之间只有敌对关系,则输出No way
。
输入样例:
7 8 4
5 6 1
2 7 -1
1 3 1
3 4 1
6 7 -1
1 2 1
1 4 1
2 3 -1
3 4
5 7
2 3
7 2
输出样例:
No problem
OK
OK but...
No way
对于这题,是一个查并集的方法来实现
我也刚学会,写一下吧
对于一堆数据,我们把他们存到一个数组里面去
先初始化
数组a 1 2 3 4 5 6
1 2 3 4 5 6
一开始初始化为自己
再根据题目的意思进行站队
比如1把2,3交朋友 5和4,6交朋友
数组就变化了
a 1 2 3 4 5 6
1 1 1 5 5 5
那么这个数组就变成了1和5两个朋友圈,1和5是这个朋友圈的群主
2,3有共同朋友1; 4,6有共同朋友5;
a[2]=1;a[3]=1;a[4]=5;a[6]=5;
我们用find()函数来找到他们的朋友圈群主来看他们是不是朋友关系(朋友的朋友就是朋友)
int find(int x){
if(a[x]!=x){//就是x有朋友了,且他不是这个朋友圈群主
return x=find(a[x])//那么找到x的这个朋友,看看他是不是这个朋友圈群主
}
return x;//如果x是朋友圈群主,就把他返回
}
有的题目还得根据给定的信息来确定群主的更替
定义一个join函数
join(int x,int y){
int fx=find(x);
int fy=find(y);x和y两个群体的群主,如果是x的群主收买了y群的群主
a[x]=fy;如果是两个群主合并了,那么任意一个都行
}
对于这题我们找到他们的朋友关系和敌人关系就行了
所以,我们还得记录一下他们是不是敌对关系
这个就比较简单了,敌人的敌人不一定是朋友,所以这个不用进行查并集,直接记录就行
用一个二维数组来记录g[a][b]表示a和b的敌对关系,不要忘记对g[b][a]进行赋值,他询问的两人没有先后顺序之分哦
最后按照题目要求输出就行了
#include <bits/stdc++.h>
using namespace std;
int parent[105];
int d[105][105];
int n;
int find(int x){
if(parent[x]!=x) parent[x]=find(parent[x]);
return parent[x];
}
int main(){
int k,m;
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
parent[i]=i;
}
while(m--){//宾客之间的关系
int a,b,c;
cin>>a>>b>>c;
if(c==1) parent[find(a)]=find(b);//让ab当朋友
else if(c==-1){
d[a][b]=1;
d[b][a]=1;//ab是敌人记录下来
}
}
while(k--){
int a,b;
cin>>a>>b;
if(d[a][b]==1){//两个人是敌人
if(parent[find(a)]==find(b)){//又是朋友
cout<<"OK but..."<<endl;
}
else cout<<"No way"<<endl;
}
else if(parent[find(a)]==find(b)){//两个人是朋友不是敌人
cout<<"No problem"<<endl;
}
else cout<<"OK"<<endl;//既不是敌人也不是朋友
}
return 0;
}
包装机
一种自动包装机的结构如图 1 所示。首先机器中有 N 条轨道,放置了一些物品。轨道下面有一个筐。当某条轨道的按钮被按下时,活塞向左推动,将轨道尽头的一件物品推落筐中。当 0 号按钮被按下时,机械手将抓取筐顶部的一件物品,放到流水线上。图 2 显示了顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态。
图1 自动包装机的结构
图 2 顺序按下按钮 3、2、3、0、1、2、0 后包装机的状态
一种特殊情况是,因为筐的容量是有限的,当筐已经满了,但仍然有某条轨道的按钮被按下时,系统应强制启动 0 号键,先从筐里抓出一件物品,再将对应轨道的物品推落。此外,如果轨道已经空了,再按对应的按钮不会发生任何事;同样的,如果筐是空的,按 0 号按钮也不会发生任何事。
现给定一系列按钮操作,请你依次列出流水线上的物品。
输入格式:
输入第一行给出 3 个正整数 N(≤100)、M(≤1000)和 Smax(≤100),分别为轨道的条数(于是轨道从 1 到 N 编号)、每条轨道初始放置的物品数量、以及筐的最大容量。随后 N 行,每行给出 M 个英文大写字母,表示每条轨道的初始物品摆放。
最后一行给出一系列数字,顺序对应被按下的按钮编号,直到 −1 标志输入结束,这个数字不要处理。数字间以空格分隔。题目保证至少会取出一件物品放在流水线上。
输出格式:
在一行中顺序输出流水线上的物品,不得有任何空格。
输入样例:
3 4 4
GPLT
PATA
OMSA
3 2 3 0 1 2 0 2 2 0 -1
输出样例:
MATA
这题很明显就是一个stack的模拟运用,
对与这个筐(一个stack)和好几个轨道进行操作
轨道是先进先出,这不就符合我们队列的要求了
所以我们这题就直接用stack和queue来解决就行了
stack模拟筐,queue模拟轨道
对于这题的情况,就这么几种,就是输入的值为0,大于0,-1
-1直接退出输入,比较好解决,当输入值为0 时:我们就对筐进行操作
如果筐不是空的,里面有东西,那我们就把筐最上面的东西取出来,放在流水线上(打印出来)
如果是空的我们就不进行任何操作
当输入值大于0时: 我们就得一边对筐进行操作,一边对轨道进行操作
如果输入的这个轨道不是空的,并且筐没有满,我们就从轨道上取一个物品下来,放到框里面
如果轨道不是空的,但是筐是满的,我们就把筐里面的东西放在流水线上,再从轨道上取一个东西下来
轨道如果是空的,那我们的操作就无效,不用再取操作
#include <bits/stdc++.h>
using namespace std;
int n,m,s;
queue<char> gd[105];
stack<char> st;
char a;
int main(){
cin>>n>>m>>s;
for(int i=1;i<=n;i++){//n个轨道
for(int j=1;j<=m;j++){//每个轨道m个物品
cin>>a;
gd[i].push(a);
}
}
while(true){
int cz;
cin>>cz;//输入操作
if(cz==-1) break;//输入-1就结束
if(cz==0&&!st.empty()){//输入的是0并且这个栈不是空的
char b=st.top();//把顶端的物品取出放到流水线上
printf("%c",b);
st.pop();
}
if(cz>0&&st.size()<s&&gd[cz].size()){//cz>0说明是对轨道进行了操作
st.push(gd[cz].front());//筐没有满,可以放下大小,并且轨道不是空的
gd[cz].pop();
}
else if(cz>0&&st.size()==s&&gd[cz].size()){//筐满了,得拿出一件在放东西进去
char b=st.top();//把顶端的物品取出放到流水线上
printf("%c",b);
st.pop();
st.push(gd[cz].front());
gd[cz].pop();
}
}
return 0;
}
愿天下有情人都是失散多年的兄妹
呵呵。大家都知道五服以内不得通婚,即两个人最近的共同祖先如果在五代以内(即本人、父母、祖父母、曾祖父母、高祖父母)则不可通婚。本题就请你帮助一对有情人判断一下,他们究竟是否可以成婚?
输入格式:
输入第一行给出一个正整数N
(2 ≤ N
≤104),随后N
行,每行按以下格式给出一个人的信息:
本人ID 性别 父亲ID 母亲ID
其中ID
是5位数字,每人不同;性别M
代表男性、F
代表女性。如果某人的父亲或母亲已经不可考,则相应的ID
位置上标记为-1
。
接下来给出一个正整数K
,随后K
行,每行给出一对有情人的ID
,其间以空格分隔。
注意:题目保证两个人是同辈,每人只有一个性别,并且血缘关系网中没有乱伦或隔辈成婚的情况。
输出格式:
对每一对有情人,判断他们的关系是否可以通婚:如果两人是同性,输出Never Mind
;如果是异性并且关系出了五服,输出Yes
;如果异性关系未出五服,输出No
。
输入样例:
24
00001 M 01111 -1
00002 F 02222 03333
00003 M 02222 03333
00004 F 04444 03333
00005 M 04444 05555
00006 F 04444 05555
00007 F 06666 07777
00008 M 06666 07777
00009 M 00001 00002
00010 M 00003 00006
00011 F 00005 00007
00012 F 00008 08888
00013 F 00009 00011
00014 M 00010 09999
00015 M 00010 09999
00016 M 10000 00012
00017 F -1 00012
00018 F 11000 00013
00019 F 11100 00018
00020 F 00015 11110
00021 M 11100 00020
00022 M 00016 -1
00023 M 10012 00017
00024 M 00022 10013
9
00021 00024
00019 00024
00011 00012
00022 00018
00001 00004
00013 00016
00017 00015
00019 00021
00010 00011
输出样例:
Never Mind
Yes
Never Mind
No
Yes
No
Yes
No
No
这题有二叉树的感觉,一个人他就一个父亲和母亲,或者它的父母不可考,也就是没有父母
人
父亲 母亲
父亲 母亲 父亲 母亲
类似于这样的,但是我不会写树....所有看了别人的数组记录,再dfs
dfs(x,num)num用来记录代数,结束条件为dfs超过了四次,也就是他们的关系是五代之外,可以结婚,x就是这个人,我们再dfs(y,num)先对x进行dfs把他的五代内的亲戚标记一下,再对y进行dfs,如果他们两个人的五代之内有相同的亲戚,说明他们是失散多年的兄妹,呜呜呜
所有我们就得写一个vis数组来记录两个人的亲戚,对与他们的性别我们也得记录,因为封建思想,同性恋是不可能的,再来一个sexu数组记录性别;
对于他们关系的存图,我们可以用二维数组也可以用vector数组来记录;
先输入他们的关系,再对他们进行查户口
#include <bits/stdc++.h>
using namespace std;
int n,k;
vector <int> gx[100005];//存储关系
bool vis[100005];//
char sexu[100005];
bool flag;
void dfs(int x,int num){//num用来记录几代
if(num>=4){//已经不在五代之内
return ;
}
for(int i=0;i<gx[x].size();i++){//对x这个人的父母进行查询
if(!vis[gx[x][i]]){
vis[gx[x][i]]=1;//标记他的父母
dfs(gx[x][i],num+1);
}
else flag=true;//如果这个人早就出先过了,说明这两个人在五代之内
}
}
int main(){
cin>>n;
int r,fa,ma;
for(int i=0;i<n;i++){
cin>>r>>sexu[r]>>fa>>ma;
if(fa!=-1){//如果他的父亲不可考,那我们就认为他没有父亲
gx[r].push_back(fa);
sexu[fa]='M';
}
if(ma!=-1){
gx[r].push_back(ma);
sexu[ma]='F';
}
}
cin>>k;
for(int i=0;i<k;i++){//进行k次询问
int a,b;
cin>>a>>b;
if(sexu[a]==sexu[b]){
cout<<"Never Mind"<<endl;//封建思想,同性不能结婚
}
else{
memset(vis,0,sizeof(vis));//对vis数组进行初始化
vis[a]=1;
vis[b]=1;
flag=false;
dfs(a,0);//先找出x的所有五代内的亲戚
dfs(b,0);//再找y的五代内的亲戚,如果有重复就说明两个人是近亲结婚
if(flag){
cout<<"No"<<endl;
}
else cout<<"Yes"<<endl;
}
}
return 0;
}