2022团队天梯赛答案解析

L1-1 今天我要赢

在这里插入图片描述

#include<iostream>

using namespace std;

int main(){
    cout << "I'm gonna win! Today!" << endl;
    cout << "2022-04-23";
    
    return 0;
}

L1-2 种钻石

在这里插入图片描述

#include<iostream>

using namespace std;

int main(){
    int a, b;
    cin >> a >> b;
    
    cout << a / b << endl;
    
    return 0;
}

C++中两数相除不是整数时,为向下取整。

L1-3 谁能进图书馆

在这里插入图片描述
在这里插入图片描述
这种模拟题一定要先列出步骤再写,不然容易漏掉情况
请添加图片描述

# include<iostream>

using namespace std;

int main(){
    int j, p, x1, x2;
    cin >> j >> p >> x1 >> x2;
    
    if (x1 < j && x2 < j) 
        cout << "zhang da zai lai ba";
    else if (x1 < j && x2 >= p) {
        printf("%d-Y %d-Y\n", x1, x2);
        printf("qing 2 zhao gu hao 1");
    }      
    else if (x1 < j && x2 >=j && x2 < p) {
        printf("%d-N %d-Y\n", x1, x2);
        printf("2: huan ying ru guan");
    }
    else if (x1 >= p && x2 < j) {
        printf("%d-Y %d-Y\n", x1, x2);        
        printf("qing 1 zhao gu hao 2");
    }
    else if (x1 >= j && x2 < j && x1 < p) {
        printf("%d-Y %d-N\n", x1, x2);
        printf("1: huan ying ru guan");
    }
    else if (x1 >= j && x2 >= j){
        printf("%d-Y %d-Y\n", x1, x2);
        cout << "huan ying ru guan";
    }
    
    return 0;
}

还有一分没过,没找到原因。

L1-4 拯救外星人

在这里插入图片描述

#include<iostream>

using namespace std;

int main(){
    int a, b;
    cin >> a >> b;
    int c = a + b;

    int res = 1;
    for (int i = 1; i <= c; i ++) res *= i; 
    
    cout << res;
    
    return 0;
}

L1-5 试试手气

在这里插入图片描述
在这里插入图片描述
第一次直接进行处理,如果他是6就将他的初始状态定为5,如果他不是6就将他的初始状态定为6,因此需要将while中的循环条件改为n>=2。

#include<iostream>

using namespace std;

const int N = 10;

int f[N]; //存每个骰子的数
int st[N]; //存骰子哪个状态已经出现过

int main(){
    int n;
    for (int i = 0; i < 6; i ++){
        cin >> f[i];
        st[i] = f[i];
        
        if (f[i] == 6) f[i] = 5;
        else f[i] = 6;
    }
    
    cin >> n;
    while(n >= 2){
        for (int i = 0; i < 6; i ++){
            f[i] --;
            if (f[i] == st[i]) f[i] --;
        }
        n --;
    }
    
    //检测空格需要分开输出
    for (int i = 0; i < 5; i ++) cout << f[i] << " ";
    cout << f[5];
    
    return 0;
}

L1-6 斯德哥尔摩火车上的题

在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<string>

using namespace std;

int main(){
    string s1, s2, ss1, ss2;
    cin >> s1 >> s2;
    
    for (int i = 1; i < s1.size(); i ++)
        if (s1[i] % 2 == s1[i - 1] % 2)
            ss1 += max(s1[i], s1[i - 1]);
    
    for (int i = 1; i < s2.size(); i ++)
        if (s2[i] % 2 == s2[i - 1] % 2)
            ss2 += max(s2[i], s2[i - 1]);
    
    if (ss1 == ss2) cout << ss1 << endl;
    else cout << ss1 << endl << ss2;
    
    return 0;
}

L1-7 机工士姆斯塔迪奥

在这里插入图片描述
纯暴力,差一分得不了

#include<iostream>

using namespace std;

const int N = 10010;

int f[N][N]; // 初始均为0

int main(){
    int n, m, q;
    cin >> n >> m >> q;
    
    while (q --){
        int a, b;
        cin >> a >> b;
        if (a == 0)
            for (int i = 1; i <= m; i ++)
                f[b][i] = 1;
        else
            for (int i = 1; i <= n; i ++)
                f[i][b] = 1;
    }
    
    int res = 0;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
            if (f[i][j] == 0) res ++;
    
    cout << res << endl;
    
    return 0;
}

AC代码,需要注意有重复攻击的情况,因此需要标记一下状态。

#include<iostream>

using namespace std;

const int N = 100010;

int row[N], col[N]; //记录某行某列是否被攻击

int main(){
    int n, m, q;
    cin >> n >> m >> q;
    
    int res = 0; //记录有多少个格子被攻击,但是会有重复记录的情况
    int cnt1 = 0, cnt2 = 0; //cnt1有几行被攻击,cnt2有几列被攻击
    while (q --){
        int a, b;
        cin >> a >> b;
        
        if (a == 0 && row[b] == 0) res += m, cnt1 ++, row[b] = 1;
        else if (a == 1 && col[b] == 0)res += n, cnt2 ++, col[b] = 1;
    }
    
    cout << n * m - res + cnt1 * cnt2;
    
    return 0;
}

L1-8 静静的推荐

在这里插入图片描述
在这里插入图片描述
如果有同学分数到达175分以上,并且PTA超过面试线,则他不需要考虑批次;如果他不满足PTA面试线,但是分数达到175分以上,则需要考虑批次。

#include<iostream>

using namespace std;

const int N = 100010;

int cnt[N]; //用来标记PTA未达到面试线的同学

int main(){
    int n, k, s;
    cin >> n >> k >> s;
    
    int res = 0;
    for (int i = 0; i < n; i ++){
        int a, b;
        cin >>  a >> b;
        if (a >= 175 && b >= s)
            res ++;
        else if (a >= 175) {
            cnt[a] ++;
            if (cnt[a] <=k) res ++;
        }
    }
    
    cout << res;
    
    return 0;
}

L2-1 插松枝

在这里插入图片描述
在这里插入图片描述
用栈去模拟盒子,队列去模拟

#include<iostream>
#include<queue>
#include<stack>

using namespace std;

queue<int> que; //模拟推送器
stack<int> st; //模拟盒子

int main()
{
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 0; i < n; i++)
    {
        int x;
        cin >> x;
        que.push(x);
    }
    
    while (que.size() || st.size())
    {
        vector<int> ans;
        int s;
        
        if (!st.empty())
        {
            s = st.top();
            st.pop();
            ans.push_back(s);
        }
        else if (!que.empty())
        {
            s = que.front();
            que.pop();
            ans.push_back(s);
        }
        
        while (1)
        {
            if (!st.empty() && st.top() <= ans.back())
            {
                s = st.top();
                st.pop();
                ans.push_back(s);
            }
            else if (!que.empty() && que.front() <= ans.back())
            {
                s = que.front();
                que.pop();
                ans.push_back(s);
            }
            else if (!st.empty() && st.top() > ans.back() && que.empty())
                break;
            else if (st.size() < m && que.front() > ans.back())
            {
                s = que.front();
                que.pop();
                st.push(s);
            }
            else if (st.size() == m && que.front() > ans.back())
                break;
            if (que.empty() && st.empty())
                break;
            else if (ans.size() == k)
                break;
        }
        
        cout << ans[0]; //又是我最讨厌的控制格式
        for (int t1 = 1; t1 < ans.size(); t1++)
            cout << " " << ans[t1];
        cout << endl;
    }
    return 0;
}

L2-2 老板的作息表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
将时间的格式直接保存成数字即可,唯一需要注意的是判断是否开始点为00:00:00,结束点为:23:59:59。

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 100010;

//用来存放一个时间段的左右端点
struct Edge{
    int l, r;
}e[N];

//让时间段按从小往大排
bool cmp(Edge a, Edge b) {
    return a.l < b.l;
}

int main(){
    int n;
    cin >> n;
    for (int i = 0; i < n; i ++){
        int h1, m1, s1, h2, m2, s2;
        scanf("%d:%d:%d - %d:%d:%d", &h1, &m1, &s1, &h2, &m2, &s2);//输入时需要注意以下
        e[i].l = h1 * 10000 + m1 * 100 + s1;
        e[i].r = h2 * 10000 + m2 * 100 + s2;
    }
    
    sort(e, e + n, cmp);
    int flag = 0;
    
    //判断是否存在开始的点不是00:00:00,结束的点不是23:59:59
    if (e[0].l != 0){
        e[n].l = 0;
        e[n].r = 0;
        flag = 1;
        
        if (e[n - 1].r != 235959)
            e[n + 1].l = 235959, flag = 2;
    }
    else if (e[n - 1].r != 235959)
        e[n].l = 235959, flag = 1;
    
    if (flag == 1){
        sort(e, e + n + 1, cmp);
        n ++;
    }
    else if (flag == 2){
        sort(e, e + n + 2, cmp);
        n += 2;
    }
    
    //输出结果
    for (int i = 0; i < n - 1; i ++)
        if (e[i].r != e[i + 1].l){
            int h = e[i].r / 10000;
            int m = e[i].r / 100 % 100;
            int s = e[i].r % 100;
            int hh = e[i + 1].l / 10000;
            int mm = e[i + 1].l / 100 % 100;
            int ss = e[i + 1].l % 100;
            
            printf("%02d:%02d:%02d - %02d:%02d:%02d\n", h, m, s, hh, mm, ss);
        }
    
    return 0;
    
}

L2-3 龙龙送外卖

在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<vector>

using namespace std;

const int N = 100010;

int n, m, root;
bool st[N]; //标记这个结点是否被访问过
int f[N]; //存放每个结点的父节点
int d[N]; //存放每个结点的深度
vector<int> v[N]; //存放每个结点的子节点

void dfs(int x){
    for (auto y : v[x])
        d[y] = d[x] + 1, dfs(y);
}

int main(){
    cin >> n >> m;
    
    for (int i = 1; i <= n; i ++){
        cin >> f[i];
        if (f[i] == -1) 
            root = i;
        else
            v[f[i]].push_back(i);
    }
    
    //将每个结点的深度算出来
    d[root] = 1;
    dfs(root);
    
    int v1 = 0, v2 = 0; //v1存放经历结点的次数,v2最大深度
    for (int i = 1; i <= m; i ++){
        int x;
        cin >> x;
        v2 = max(v2, d[x]);
        for (; x != root && !st[x]; x = f[x])
            v1 += 2, st[x] = true;
        cout << v1 - (v2 - 1) << endl;
    }
    
    return 0;
}

L2-4 大众情人

在这里插入图片描述
在这里插入图片描述
数据量比较小,直接用Floyd算法求出每个人之间的最小距离,然后遍历编号,找到异性缘最好的编号。

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

const int N = 550;

int g[N][N], sex[N], d[N];

int main(){
    int n;
    cin >> n;
    
    //初始化两人之间的距离
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= n; j ++)
            if (i == j) g[i][j] = 0;
            else g[i][j] = 1e9;
            
    for (int i = 1; i <= n; i ++){
        char c;
        int k;
        cin >> c >> k;
        if (c == 'F') sex[i] = 1; //女生
        else sex[i] = 2; //男生
        for (int j = 1; j <= k; j ++){
            int a, b;
            scanf("%d:%d", &a, &b);
            g[i][a] = b;
        }
    }
    
    //floyd算法
    for (int k = 1; k <= n; k ++)
        for (int i = 1; i <= n; i ++)
            for (int j = 1; j <= n; j ++)
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
                
    //求异性缘中的最大距离
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= n; j ++)
            if (sex[i] != sex[j])
                d[i] = max(d[i], g[j][i]);
                
    int d1 = 1e9, d2 = 1e9; //d1女,d2男
    for (int i = 1; i <= n; i ++){
        if (sex[i] == 2) d1 = min(d1, d[i]);
        else d2 = min(d2, d[i]);
    }
    

    vector<int> v1, v2;
    //男性的大众情人
    for (int i = 1; i <= n; i ++){
        if (sex[i] == 1) continue;
        if (d[i] == d1) v1.push_back(i); 
    }
    
    //女性的大众情人
    for (int i = 1; i <= n; i ++){
        if (sex[i] == 2) continue;
        if (d[i] == d2) v2.push_back(i);
    }
    
    
    for (int i = 0; i < v2.size(); i ++){
        cout << v2[i];
        if (i != v2.size() - 1) cout << " ";
    }
    
    cout << endl;
    
    for (int i = 0; i < v1.size(); i ++){
        cout << v1[i];
        if (i != v1.size() - 1) cout << " ";
    }
    
    return 0;
}
  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天一道题

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值