7-12 愿天下有情人都是失散多年的兄妹
分数 25
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
呵呵。大家都知道五服以内不得通婚,即两个人最近的共同祖先如果在五代以内(即本人、父母、祖父母、曾祖父母、高祖父母)则不可通婚。本题就请你帮助一对有情人判断一下,他们究竟是否可以成婚?
输入格式:
输入第一行给出一个正整数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
1.运用并查集维护查询每个人的直接父亲(由于只往上查询一级,不用递归)
2.最后用搜索判断两个人的共同祖先是否是5代以内,由于同性不能通婚,需要同时记录该孩子,双亲的性别
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<stack>
#include<queue>
using namespace std;
const int N = 1e5 + 10;//注意范围
int n, k;
struct node
{
char se;
int fa, ma;
}p[N];
int fa[N];
int find(int x)
{
if (x != fa[x])fa[x] = fa[fa[x]];//记录其直接父亲
return fa[x];
}
void unite(int x, int y)
{
int xfa = find(x), yfa = find(y);
xfa > yfa ? fa[xfa] = yfa : fa[yfa] = xfa;
}
int dfs(int x, int y, int gap)
{
if (x == -1 || y == -1)return 1;
if (gap > 5)return 1;
if (x == y)return 0;
return dfs(p[x].fa, p[y].fa, gap + 1) && dfs(p[x].fa, p[y].ma, gap + 1) && dfs(p[x].ma, p[y].fa, gap + 1) && dfs(p[x].ma, p[y].ma, gap + 1);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= 100000; i++)
{
p[i].fa = -1, p[i].ma = -1;
fa[i] = i;
}
for (int i = 1; i <= n; i++)
{
int n1;
cin >> n1;
cin >> p[n1].se >> p[n1].fa >> p[n1].ma;
if (p[n1].fa != -1)p[p[n1].fa].se = 'M', unite(n1, p[n1].fa);//父亲存在
if (p[n1].ma != -1)p[p[n1].ma].se = 'F', unite(n1, p[n1].ma);
}
int p1, p2;
cin >> k;
while (k--)
{
cin >> p1 >> p2;
if (p[p1].se == p[p2].se)puts("Never Mind");
else {
if (find(p1) != find(p2))puts("YES");
else
{
if (dfs(p1, p2, 1))puts("YES");
else puts("NO");
}
}
}
return 0;
}
7-9 排座位
分数 25
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。
输入格式:
输入第一行给出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
简单应用并查集就ok了
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 1e2 + 10;
int n, m, k;
int fa[N];
int v[N][N];
int find(int x)
{
if (x != fa[x])fa[x] = find(fa[x]);
return fa[x];
}
void unite(int x, int y)
{
fa[find(x)] = find(y);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m >> k;
for (int i = 1; i <= 105; i++)fa[i] = i;
for (int i = 1; i <= m; i++)
{
int x, y, z;
cin >> x >> y >> z;
if (z == 1)unite(x, y);
v[x][y] = v[y][x] = z;//记录敌对和朋友关系
}
for (int i = 1; i <= k; i++)
{
int x, y;
cin >> x >> y;
if (v[x][y] == 1)puts("No problem");//是朋友且不是敌对关系
else if (v[x][y] == 0)//不是直接朋友且不是敌对关系
{
if(find(x) == find(y))puts("No problem"); //有共同朋友
else puts("OK");//不是直接朋友且不是敌对关系
}
else if(v[x][y]==-1)//有敌对关系
{
if (find(x) == find(y))puts("OK but...");//有共同朋友
else puts("No way");//只有敌对关系
}
}
return 0;
}
7-11 包装机
分数 25
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
一种自动包装机的结构如图 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
栈和队列简单模拟
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<stack>
#include<queue>
using namespace std;
const int N = 110;
int n, m, smax;
queue <char> q[N];
stack <char> s;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m >> smax;
for (int i = 1; i <= n; i++)
{
char ch;
for (int j = 1; j <= m; j++)
{
cin >> ch;
q[i].push(ch);
}
}
int num;
cin >> num;
while (num != -1)
{
if (num!=0) {
if (q[num].size())
{
if (s.size() == smax)
{
cout << s.top();
s.pop();
}
s.push(q[num].front());
q[num].pop();
}
}
else
{
if (s.size())
{
cout << s.top();
s.pop();
}
}
cin >> num;
}
return 0;
}
其他简单题就不写提示了
7-1 重要的话说三遍
分数 5
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
这道超级简单的题目没有任何输入。
你只需要把这句很重要的话 —— “I'm gonna WIN!”——连续输出三遍就可以了。
注意每遍占一行,除了每行的回车不能有任何多余字符。
#include<iostream>
using namespace std;
int main()
{
for(int i=1;i<=3;i++)
printf("I'm gonna WIN!\n");
return 0;
}
7-2 日期格式化
分数 5
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
世界上不同国家有不同的写日期的习惯。比如美国人习惯写成“月-日-年”,而中国人习惯写成“年-月-日”。下面请你写个程序,自动把读入的美国格式的日期改写成中国习惯的日期。
输入格式:
输入在一行中按照“mm-dd-yyyy”的格式给出月、日、年。题目保证给出的日期是1900年元旦至今合法的日期。
输出格式:
在一行中按照“yyyy-mm-dd”的格式给出年、月、日。
输入样例:
03-15-2017
输出样例:
2017-03-15
#include<iostream>
using namespace std;
int main()
{
int m,y,d;
scanf("%d-%d-%d",&m,&d,&y);
printf("%d-%02d-%02d",y,m,d);
return 0;
}
L1-3 大笨钟
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。不过由于笨钟自己作息也不是很规律,所以敲钟并不定时。一般敲钟的点数是根据敲钟时间而定的,如果正好在某个整点敲,那么“当”数就等于那个整点数;如果过了整点,就敲下一个整点数。另外,虽然一天有24小时,钟却是只在后半天敲1~12下。例如在23:00敲钟,就是“当当当当当当当当当当当”,而到了23:01就会是“当当当当当当当当当当当当”。在午夜00:00到中午12:00期间(端点时间包括在内),笨钟是不敲的。
下面就请你写个程序,根据当前时间替大笨钟敲钟。
输入格式:
输入第一行按照hh:mm
的格式给出当前时间。其中hh
是小时,在00到23之间;mm
是分钟,在00到59之间。
输出格式:
根据当前时间替大笨钟敲钟,即在一行中输出相应数量个Dang
。如果不是敲钟期,则输出:
Only hh:mm. Too early to Dang.
其中hh:mm
是输入的时间。
输入样例1:
19:05
输出样例1:
DangDangDangDangDangDangDangDang
输入样例2:
07:05
输出样例2:
Only 07:05. Too early to Dang.
#include<iostream>
using namespace std;
int main()
{
int m,h;
scanf("%d:%d",&h,&m);
h = h-12;
if(h<=0)
{
printf("Only %02d:%02d. Too early to Dang.",h+12,m);
return 0;
}
while(h>0)
{
printf("Dang");
h--;
}
if(m)printf("Dang");
return 0;
}
L1-4 拯救外星人
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
你的外星人朋友不认得地球上的加减乘除符号,但是会算阶乘 —— 正整数 N 的阶乘记为 “N!”,是从 1 到 N 的连乘积。所以当他不知道“5+7”等于多少时,如果你告诉他等于“12!”,他就写出了“479001600”这个答案。
本题就请你写程序模仿外星人的行为。
输入格式:
输入在一行中给出两个正整数 A 和 B。
输出格式:
在一行中输出 (A+B) 的阶乘。题目保证 (A+B) 的值小于 12。
输入样例:
3 6
输出样例:
362880
#include<iostream>
using namespace std;
int main()
{
int a,b;
scanf("%d%d",&a,&b);
a+=b;
long long ans=1;
for(int i=1;i<=a;i++)
ans*=i;
printf("%lld",ans);
return 0;
}
7-5 个位数统计
分数 15
全屏浏览题目
切换布局
作者 CHEN, Yue
单位 浙江大学
给定一个 k 位整数 N=dk−110k−1+⋯+d1101+d0 (0≤di≤9, i=0,⋯,k−1, dk−1>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有 2 个 0,3 个 1,和 1 个 3。
输入格式:
每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。
输出格式:
对 N 中每一种不同的个位数字,以 D:M
的格式在一行中输出该位数字 D
及其在 N 中出现的次数 M
。要求按 D
的升序输出。
输入样例:
100311
输出样例:
0:2
1:3
3:1
#include<iostream>
#include<algorithm>
using namespace std;
string s;
int a[10],b[10], k;
int main()
{
cin >> s;
for (int i = 0; i <s.size(); i++)
{
a[s[i] - '0']++;
}
//for (int i = 0; i < 10; i++)b[a[i]] = i;
//sort(a, a + 9);
//while (!a[k])k++;
for (int i = 0; i <= 9; i++)
{
if(a[i])
printf("%d:%d\n", i, a[i]);
}
return 0;
}
L1-6 正整数A+B
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
题的目标很简单,就是求两个正整数A
和B
的和,其中A
和B
都在区间[1,1000]。稍微有点麻烦的是,输入并不保证是两个正整数。
输入格式:
输入在一行给出A
和B
,其间以空格分开。问题是A
和B
不一定是满足要求的正整数,有时候可能是超出范围的数字、负数、带小数点的实数、甚至是一堆乱码。
注意:我们把输入中出现的第1个空格认为是A
和B
的分隔。题目保证至少存在一个空格,并且B
不是一个空字符串。
输出格式:
如果输入的确是两个正整数,则按格式A + B = 和
输出。如果某个输入不合要求,则在相应位置输出?
,显然此时和也是?
。
输入样例1:
123 456
输出样例1:
123 + 456 = 579
输入样例2:
22. 18
输出样例2:
? + 18 = ?
输入样例3:
-100 blabla bla...33
输出样例3:
? + ? = ?
#include<iostream>
#include<algorithm>
#include<cmath>
#include<bits/stdc++.h>
using namespace std;
string s1, s2;
int a, b,f1,f2;
int main()
{
cin >> s1 ;
getline(cin,s2);
for (int i = 0; i < s1.size(); i++)
{
if (s1[i] >= '0' && s1[i] <= '9')f1 = 1;
else
{
f1 = 0;
break;
}
}
for (int i = 1; i < s2.size(); i++)
{
if (s2[i] >= '0' && s2[i] <= '9')f2 = 1;
else
{
f2 = 0;
break;
}
}
if (f1)
{
for (int i = 0; i < s1.size(); i++)
a = a + (s1[i]-'0') * pow(10, s1.size() - i - 1);
}
if (a < 1 || a>1000)f1 = 0;
if (f2)
{
for (int i = 1; i < s2.size(); i++)
b = b + (s2[i] - '0') * pow(10, s2.size() - i - 1);
}
if (b < 1 || b>1000)f2 = 0;
if (f1 && f2)printf("%d + %d = %d\n", a, b, a + b);
else if (!f1 && !f2)printf("? + ? = ?\n");
else if (f1 && !f2)printf("%d + ? = ?\n", a);
else printf("? + %d = ?\n", b);
return 0;
}
7-7 打印沙漏
分数 20
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
#include<iostream>
using namespace std;
int num,n;
char ch;
int main()
{
scanf("%d %c", &num, &ch);
for (int i = 1; i <= num; i++)
{
if (2*i*i <= (num + 1) )n = i;
else break;
}
num = (num + 1) - 2 * n * n;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 2 * n - 1; j++)
{
if (j < i )printf(" ");
else if (j >= 2 * n - 1 - i)continue;
else printf("%c",ch);
}
printf("\n");
}
for (int i = 2; i <= n; i++)
{
for (int j = 0; j < n - i; j++)printf(" ");
for (int k = 1; k <= 2 * i - 1; k++)printf("%c", ch);
printf("\n");
}
//for (int i = 1; i < n; i++)
//{
// for (int j = 0; j < 2 * n - 1; j++)
// {
// if (j < i || j >= 2 * n - 1 - i)printf(" ");
// else printf("%c", ch);
// }
// printf("\n");
//}
printf("%d\n", num);
return 0;
}
7-8 机工士姆斯塔迪奥
分数 20
全屏浏览题目
切换布局
作者 DAI, Longao
单位 杭州百腾教育科技有限公司
在 MMORPG《最终幻想14》的副本“乐欲之所瓯博讷修道院”里,BOSS 机工士姆斯塔迪奥将会接受玩家的挑战。
你需要处理这个副本其中的一个机制:N×M 大小的地图被拆分为了 N×M 个 1×1 的格子,BOSS 会选择若干行或/及若干列释放技能,玩家不能站在释放技能的方格上,否则就会被击中而失败。
给定 BOSS 所有释放技能的行或列信息,请你计算出最后有多少个格子是安全的。
输入格式:
输入第一行是三个整数 N,M,Q (1≤N×M≤105,0≤Q≤1000),表示地图为 N 行 M 列大小以及选择的行/列数量。
接下来 Q 行,每行两个数 Ti,Ci,其中 Ti=0 表示 BOSS 选择的是一整行,Ti=1 表示选择的是一整列,Ci 为选择的行号/列号。行和列的编号均从 1 开始。
输出格式:
输出一个数,表示安全格子的数量。
输入样例:
5 5 3
0 2
0 4
1 3
输出样例:
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int n, m, q, t, c, ans, hang, lie, vish[N], visl[N];
int main()
{
scanf("%d %d %d", &n, &m, &q);
ans = n * m;
for (int i = 1; i <= q; i++)
{
scanf("%d %d", &t, &c);
if (t == 0 && !vish[c])
{
vish[c] = 1;
hang++;
ans = ans - m + lie;
}
if (t == 1 && !visl[c])
{
visl[c] = 1;
lie++;
ans = ans - n + hang;
}
}
printf("%d\n", ans);
return 0;
}
12
L2-2 名人堂与代金券
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
对于在中国大学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
#include<bits/stdc++.h>
using namespace std;
int n,g,k,sum;
struct st
{
string nam;
int sco;
}stu[10005];
//bool cmp(st s1, st s2)
//{
// return s1.sco > s2.sco || (s1.sco == s2.sco && s1.nam[0] < s2.nam[0]) || (s1.sco == s2.sco && s1.nam[0] == s2.nam[0] && s1.nam[1] < s2.nam[1]);
//}
bool cmp(st s1, st s2)
{
return s1.sco > s2.sco || (s1.sco == s2.sco && s1.nam < s2.nam) ;
}
int main()
{
scanf("%d %d %d", &n, &g, &k);
for (int i = 0; i < n; i++)
{
cin >> stu[i].nam >> stu[i].sco;
if (stu[i].sco >= g)sum += 50;
else if(stu[i].sco>=60)sum += 20;
}
sort(stu, stu + n, cmp);
printf("%d\n", sum);
int rank = 1,de=0;
for (int i = 0; i < n; i++)
{
if (rank <= k) {
//if (i >= 1 && stu[i].sco < stu[i - 1].sco)
//{
// rank += de, de = 1;
//}
//else de++;
if (i >= 1 && stu[i].sco == stu[i - 1].sco)
{
de++;
}
else if(i>=1&&stu[i].sco<stu[i-1].sco)
{
rank = rank + 1 + de, de = 0;
}
if (rank <= k) {
printf("%d ", rank);
cout << stu[i].nam;
printf(" %d\n", stu[i].sco);
}
}
}
return 0;
}