『题解』UVa online judge UVA12541 Birthdates
\(\textsf{update on 2022/6/5 修改了错别字。}\)
题目大意
给定 \(n\) 个人的名字,出生年月日,求年龄最大的和最小的人。
思路
使用万能的 STL,排序一遍过,用一个结构体存储每个人的信息。
但是与其它题解不同的是,其它题解用的都是 cmp 函数来排序,我们使用 lambda 表达式。
lambda 表达式
什么是 lambda 表达式呢?它就相当于一个函数,可以直接当做一个变量,直接传入 sort
函数,就像 sort
函数写的 cmp 函数一样。
lambda 表达式格式如下:
[捕获列表(可省略)](参数列表(可省略))->返回类型{函数内容}
捕获列表(可省略)
捕获列表决定了 lambda 表达式能访问的外部变量,以及访问方式。
[]
(省略):不捕获任何外部变量。[&]
:捕获所有局部变量,并以引用方式访问,就是说可以修改所有函数外变量。[=]
:同上,只不过是按值访问,注意!这里不是复制一遍局部变量,而是将局部变量当作一个常量引入表达式内,就是说你的所有局部变量(除了列表中特殊指定)在你的表达式中都变成了一个常量,不可赋值。[=,&a]
:同[=]
,只不过 \(a\) 变量按引用访问,是不是很精准?[a]
:按值捕获变量 \(a\),相当于只捕获变量 \(a\) 的[=]
。- ......
这些参数可以自己改变,随心所欲地控制要捕获的变量。
lambda 表达式可真是精妙,连能访问什么外部变量及访问方式都可以指定。
参数列表(可省略)
这里就是字面意思,放置这个函数的参数,和普通函数一样qwq。
返回类型
就是写在普通函数前面的返回类型,在 lambda 表达式中用一个小箭头 ->
来表示,是不是很形象?
函数内容
顾名思义,就是写在函数里的内容,就是这个函数要干什么。
lambda 表达式能干什么?
看了这么多非人话,来看看 lambda 的实际应用吧。
lambda 表达式用处很多,这里举几个例子qwq。
你可以直接将一个变量初始化为一个 lambda 表达式,变量类型写为 auto
,然后就可以将这个变量当作一个函数了,像这样:
auto add=[](int a,int b)->int{return a+b;};
cout << add(1,2) << endl;
结果为 \(3\),是不是很神奇?
来看看引用相关的例子:
// main函数内
int main(){
int a=233,b=114514;
// 所有外部变量都按值捕获,只有 b 是引用方式捕获
auto lbd=[=,&b]()->void{
// a=114514; // a 是按值捕获的,表达式中是一个常量,不能修改
b=1919810;
};
lbd();
cout << a << " " << b << endl;
return 0;
}
输出结果:
233 1919810
本题
和大家一样 node
结构体存个人信息,只不过 sort
函数有些变换:
// lambda表达式:
// 捕获列表:空
// 参数:node类型两个变量 a,b,和普通 cmp 函数一样
// 返回值:bool 同 cmp
sort(a+1,a+n+1,[](node a,node b)->bool{ // lambda表达式
// 相当于一个 cmp 函数,所以cmp 函数照搬
if(a.year!=b.year) return a.year<b.year; // 首先是年份不相同,先比较年份
if(a.month!=b.month) return a.month<b.month; // 其次月份
return a.date<b.date; // 最后日期
});
代码
#include <iostream>
#include <algorithm>
using namespace std;
struct node{ // 存放个人信息的结构体
int year,month,date;
string name;
}a[205];
int n;
int main(){
cin >> n;
for(int i=1; i<=n; i++){
cin >> a[i].name >> a[i].date >> a[i].month >> a[i].year;
}
sort(a+1,a+1+n,[](node a,node b)->bool{ // lambda表达式
if(a.year!=b.year) return a.year<b.year; // 首先是年份不相同,先比较年份
if(a.month!=b.month) return a.month<b.month; // 其次月份
return a.date<b.date; // 最后日期
});
// 排序后最后一个和第一个就分别是最大的和最小的。
cout << a[n].name << endl << a[1].name << endl;
return 0;
}