L2-039 清点代码库 (25 分)【2021年天梯赛总决赛L2-3,签到题?】【题解+参赛感悟】

题目:L2-039 清点代码库 (25 分)
内容:

在这里插入图片描述

上图转自新浪微博:“阿里代码库有几亿行代码,但其中有很多功能重复的代码,比如单单快排就被重写了几百遍。请设计一个程序,能够将代码库中所有功能重复的代码找出。各位大佬有啥想法,我当时就懵了,然后就挂了。。。”
这里我们把问题简化一下:首先假设两个功能模块如果接受同样的输入,总是给出同样的输出,则它们就是功能重复的;其次我们把每个模块的输出都简化为一个整数(在 int 范围内)。于是我们可以设计一系列输入,检查所有功能模块的对应输出,从而查出功能重复的代码。你的任务就是设计并实现这个简化问题的解决方案。

输入格式:

输入在第一行中给出 2 个正整数,依次为 N(≤10^4 ​​ )和 M(≤10^​2 ​​ ),
对应功能模块的个数和系列测试输入的个数。
随后 N 行,每行给出一个功能模块的 M 个对应输出,数字间以空格分隔。

输出格式:

首先在第一行输出不同功能的个数 K。
随后 K 行,每行给出具有这个功能的模块的个数,以及这个功能的对应输出。
数字间以 1 个空格分隔,行首尾不得有多余空格。
输出首先按模块个数非递增顺序,
如果有并列,则按输出序列的递增序给出。
注:
所谓数列 { A​1​​ , …, A​M} 比 { B​1​​ , …, B​M​​ } 大,是指存在 1≤i<M,
使得 A​​ 1=B​1​​ ,…,A​i​​ =B​i​​ 成立,且 A​i+1​​ >B​i+1

输入样例:

7 3
35 28 74
-1 -1 22
28 74 35
-1 -1 22
11 66 0
35 28 74
35 28 74

输出样例:

4
3 35 28 74
2 -1 -1 22
1 11 66 0
1 28 74 35

分析:
这道题的题意其实很简单,也就是统计一下不同功能块的个数和相同的输入有多少个,最直接的做法就是去重后排序就好了。

但是这道题的难点在于怎么去重,怎么比较,若是用循环逐一比较的话肯定是会超时的,去重我们可以用set和map,但是要统计数量,那么自然是用map啦,如果用map的话,那么自然用个数来作为它的值,但是键用什么好呢,因为m的值是在变化的,所以不可能用简单的数组,答案就呼之欲出了,用vector来作为键,可是vector能作为map的键吗?很多人也许想到了这里,就自然而然的认为vector不能够作为map的键(既然想出来了,那么就实践一下,万一可以呢, 所以不要否定自己的任何想法),不过事实并非这样,vector是可以作为map的键的,vector是可以比较大小的,在vector内部是重载了小于符号的。知道这点之后一切就都好办了,直接写就完了,注意map的元素是pair类型的,所以在提取数据的时候注意一下数据类型就A了。所以说这么多就是想说这道题不难,只要想到vector可以比较大小,一切就迎刃而解啦!

AC代码:

#include<bits/stdc++.h>
using namespace std;
map<vector<int>, int> mp;    // 用map统计输入系列测试输入的种类以及个数
struct no{      //将map的元素重新整理为结构体,并对结构体重载小于号
    vector<int> v;
    int ct;
    bool operator < (const no&vv) const{
        if(ct==vv.ct) return v<vv.v;
        return ct>vv.ct;
    }
};
vector<no> ans;  //不推荐用结构体数组,所以用动态数组vector存答案ans
int main(){
    cin>>n>>m;
    while(n--){
        vector<int> v;
        for(int i=0;i<m;i++){
            int num;
            cin>>num;
            v.push_back(num);
        }
        if(mp.count(v)) mp[v]++;
        else mp[v]=1;
    }
    cout<<mp.size()<<endl; //不同功能的个数
    for(auto i: mp){
        no nn;
        nn.ct=i.second;
        nn.v = i.first;
        ans.push_back(nn);
    }
    sort(ans.begin(), ans.end()); //排序后输出
    for(auto i:ans){
        cout<<i.ct;
        for(auto j:i.v) cout<<" "<<j;
        cout<<endl;
    }
    return 0;
}

(以下内容可以不看了)
参赛感悟

这次的比赛确实要比去年的题要简单很多,吉老师出的题也有人能够做出来了,比赛过程中给我影响较为深刻的是在大约开考一个小时的时候就有大佬(Orz)把L2和L3(除了L3的最后一个)做完了,这时候我才刚刚做完L1,差距明显到无地自容,正如听过的那样,学霸考试考100分,是因为卷子只有100分,你考90分是因为你只能考90分。

赛前刷了十几道L3以前的试题,也研究了一下面向样例编程(骗分 ),但是L3是一道题都没有做出来,即使是最后留下来了近40分钟做L3,如果40分钟只做一个题的话,肯定选择L3-2,可是我却花了20分钟看L3-1剩下的时间看L3-2的题目,这就很不好,贪心也不是这样贪心的,所以与一些奖项失之交臂,留下了遗憾,但是现在也是释怀了,毕竟自己水平还不够,进步空间还很大。

如果有幸被正在准备接下来天梯赛的未来祖国栋梁翻阅到,不妨看看我的建议:

  • 天梯赛只是起点,很基础的开始,只适合作为算法的门槛竞赛,一定不要引以为傲。
  • 备考的话一定要刷天梯赛的原题,pat乙级试题,pat甲级试题可选刷。
  • 天梯赛的很多题其实并不注重算法,只是让你解决一个可能实际的问题,按部就班的做就好了。
  • 天梯赛的题很巧妙,很多题用很少的代码或者小技巧就能够通过。
    - L3有时候可能是面向样例编程
  • 算法的定义是有穷的指令集,要学会通过学习算法处理生活中的实际问题。
  • 一定要总结,要有一套自己的解题过程。
  • 学习生活再苦再累,也要好好吃饭。

比赛点滴:

今年出现了比去年线上考试还要糟的系统问题,导致比赛延时20分钟。
西南赛区的赛点在成都信息工程大学,有午餐券和晚餐劵,均为自助餐,餐厅环境良好,菜品丰富。
考场有人因管不住脚重启电脑

作者:跑龙套的花灵龙
时间:2021/04/26 22:18

  • 32
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值