『题解』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;
}
posted @ 2022-01-21 21:29  仙山有茗  阅读(35)  评论(0编辑  收藏  举报