Openjudge 3.1.6377 解析

这道题的网址

OpenJudge - 6377:生日相同 2.0icon-default.png?t=N7T8http://noi.openjudge.cn/ch0301/6377/

请速览一遍原题

Openjudge 3.1.6377 解析_第1张图片

拿到题,读一遍,了解个大概,进行

题面分析

一、这道题题面提示使用什么?

Openjudge 3.1.6377 解析_第2张图片

数据结构!!!

在正常的算法竞赛学习过程中,我们先后会学到(常用的几种):

① 数组

② 结构体

③ 联合体

……

那么这道题,输入成分相似,而且分类明确,集合性强。用什么?(大声回答)

当然是结构体(当然数组也能用,不过比较复杂,本篇中不多赘述)

结构体怎么用?(某人:“不知道”)

这样的人估计有很多,如果你也是这样的人,请去这个网站学习一下[旺柴]:

【官方 MV】Never Gonna Give You Up - Rick Astley_哔哩哔哩_bilibili-, 视频播放量 83747542、弹幕量 117933、点赞数 2190126、投硬币枚数 932189、收藏人数 1152828、转发人数 341823, 视频作者 索尼音乐中国, 作者简介 更多音乐请右滑收藏夹~欢迎投稿字幕,相关视频:KANA-BOON「バトンロード」(TV动画《博人传 火影忍者新时代》OP),大家好,我是Rick Astley,今天我入驻b站了! doge,当我们在校园合唱节中唱你被骗了……,【官方MV】LiSA「紅蓮華」(TV动画《鬼灭之刃》OP),King Gnu「BOY」(TV动画《国王排名》OP),【年龄和声音终于一致了】rick应邀重新演绎经典MV,2024开年诈骗!Rick Astley《Never Gonna Give You Up》 摇滚跨年夜 20240101,油管官方惨遭Rickroll,【8K】MV 宮本浩次 《冬之花》「冬の花」—— 收藏级画质,【春节】刘德华《恭喜发财》春节必听神曲!祝大家新年快乐!icon-default.png?t=N7T8https://www.bilibili.com/video/BV1GJ411x7h7/?spm_id_from=333.337.search-card.all.click(愿者上钩)

既然知道了这道题用结构体,定义它,就迈出了第一步。

二、注意一些细节

要特别注意数据类型、输出格式、特殊值等规定。

比如说

1.输入表示有n个学生,n ≤ 180。这就告诉我们无需定义太多的结构体空间;但若是定义正好180个,这是一种不好的做法。大部分程序设计者无法一次性非常准确地控制好访问边界,特别容易访问超区。如果你不是很会控制和统计空间数量/长度,那应该留出宽限,所以应该空出几十个空空间(但这并不是说你可以不认真统计使用数量)。对于本题,差不多

Stu stu[200];

就够了

2.输入顺序:名字(string)、月(int)、日(int),出生月(1 ≤ m ≤ 12)、日(1 ≤ d ≤ 31)。单空格分隔。

3.输出顺序:

相同的生日(月+空格+日)+空格+所有在当天出生的学生的名字;

相同的生日(月+空格+日)+空格+所有在当天出生的学生的名字;

相同的生日(月+空格+日)+空格+所有在当天出生的学生的名字;

……

日期从前到后(很重要),名字按名字从短到长按序输出,长度相同的按字典序(就是字符串对应位置元素的ASCII码比较)输出。如没有生日相同的学生,输出”None”。

很明显:如果只有一个人出生于一个单独的生日,那这个生日的日期和这个人的名字都不应输出。

三、看样例,人工模拟

这一步不讲了

那咱们开始动手吧

一、先把这几句写好

#include
using namespace std;
int main()
{
    //sentences
    return 0;
}

二、定义一个结构体并声明空间。

很明显,该结构体需要包括名字、出生月、出生日几个成分。它们的类型分别是string(这里不推荐用数组或其它的), int , int。

struct Stu
{
	string ftn;//ftn是first name的缩写
	int mon;//month
	int dat;//date,实际上用day更好,这里就不改了
}stu[200];//特别要注意两个大小写不同的Stu和stu,Stu是类型名,而stu是变量名

三、然后开始写main()里面的内容

数量值输入不用说,挨个填入数据也是简单的。

然后,数据有了,你该怎么办?

如果你直接进行统计,需要建很多的表示月、日、数量统计、名字统计的变量。

如此繁杂,那就是因为数据无序

该触发关键词了——排序。

特别要注意的是排序的下标。如果下标从1开始,那应该从哪几个元素开始排序呢(请各位思考一下)

结构体排序,少不了?(大声回答)答:cmp函数。

本题的cmp函数直接按输出要求排列好就可以。

写cmp函数需要注意:①把分支结构思路理清晰;②将比较量选对;③将返回值类型写对。

bool cmp(Stu a, Stu b)/这里可以理解为比较的是类数组元素的前、后两个元素
{
	if (a.mon != b.mon) return a.mon < b.mon;//月份不同,小的在前
	else if (a.dat != b.dat) return a.dat < b.dat;//月份相同,日子不同,小的在前
	else if (a.ftn.size() != b.ftn.size()) return a.ftn.size() < b.ftn.size();
    //生日完全相同,名字长度不同,短的在前
	else return a.ftn < b.ftn;//以上均相同,名字字母逐个比较,相对小的在前
    //return一定要写成对应量的大小关系,而不是两个结构体的大小关系,不然编译器提示重载错误
}

then:排序后可以进行输出测试,测试完注释掉。

then:写上下一个for()开始设计输出。

咱们要想一个问题:什么样的数据,有什么样的特征,怎么处理它?

1.现在排好顺序的数据,月日罗列整齐,生日单调递增。那这样的数列如何判断日期是单独(即只有一个人出生在这天)的呢?

很简单,大家看这个数列

6,6,6,6,6,6,6,6,7,9,9,9,9,9,9,…

中间的这个7,上面一项与他不相等,下面一项也与它不相等。那么他就是单独的(确信)。

2.那如果他与上面一项的不相等,那至少说明什么?

答:他的生日与上一项不同,是一个新数列的开端

题目规定了,所有组别要先输出生日,那你要用bool控制一下,如果是一个开端,就这么做。但必须注意,这种情况,包括了上一种情况。

我说了这么多话,但你却没被绕进去,原因——很多重复使用的句子。

那很多聪明的人(比如我)会想到一个办法,咱们用两个布尔变量代表两个判断句。

假设说A=某个人和他上面的人(结构体)生日完全相同,B=A=某个人和他上面的人(结构体)生日完全相同。

那第一种情况可以视为!A&&!B,或写作!(A||B);第二种情况可以视为!A。

而遇到第一种情况,就别浪费时间了,写在前面,直接continue;

遇到第二种情况,注意,此时的第二种情况不包括第一种情况了(因为已经continue),所以直接输出日期+名字,注意格式(比如空格)。

如果是其他的情况(A为真),直接输出名字即可,但如果出现(A&&!B)的现象,表明到了末尾,直接加换行。但注意这两种情况是不冲突的,所以写为:

		if(A) 
		{
			cout<

但是如果什么都没输出怎么办,不能空着。

我这回没有好点子了,加一个变量控制是否输出,只要输出(只要有cout),该变量就是true;如果是false,输出None,注意大小写。

上代码

#include//万能头
using namespace std;
struct Stu
{
	string ftn;
	int mon;
	int dat;
}stu[200];
bool cmp(Stu a, Stu b)
{
	if (a.mon != b.mon) return a.mon < b.mon;
	else if (a.dat != b.dat) return a.dat < b.dat;
	else if (a.ftn.size() != b.ftn.size()) return a.ftn.size() < b.ftn.size();
	else return a.ftn < b.ftn;
}
bool A,B,ne=false;//两个说法,A为向上判断,B为向下判断,ne控制是否有输出(是否有相同)
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> stu[i].ftn >> stu[i].mon >> stu[i].dat;
	sort(stu + 1, stu + 1 + n, cmp);
	
//	for(int i=1;i<=n;i++)
//		cout<

 Openjudge 3.1.6377 解析_第3张图片

Tips

1.原创内容,禁止盗用,如需转载请注明出处;

2.有错敬请指正,欢迎讨论区交流。

你可能感兴趣的:(精编题解,c++)