2023年第八届团队程序设计天梯赛选拔校赛(三)题解

2023-05-16

文章目录

  • 7-1 认识时钟
  • 7-2 修剪灌木
  • 7-3 求和运算
  • 7-4 合并数组
  • 7-5 骰子游戏
  • 7-6 字符串最大跨距
  • 7-7 上台阶
  • 7-8 A-B
  • 7-9 括号匹配
  • 7-10 列出连通集
  • 7-12 哲哲打游戏
  • 7-13 喊山

标号标题分数提交通过率
7-1认识时钟536/99(36.36%)
7-2修剪灌木530/103(29.13%)
7-3求和运算1029/81(35.80%)
7-4合并数组1027/127(21.26%)
7-5骰子游戏1514/94(14.89%)
7-6字符串最大跨距1516/116(13.79%)
7-7走楼梯升级版2021/96(21.88%)
7-8A-B2025/95(26.32%)
7-9括号匹配253/155(1.94%)
7-10列出连通集255/25(20.00%)
7-11秀恩爱分得快250/40(0.00%)
7-12哲哲打游戏254/18(22.22%)
7-13喊山301/28(3.57%)
7-14地铁一日游300/6(0.00%)
7-15可怜的复杂度300/13(0.00%)

7-1 认识时钟

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n;
    cin >> n;
    cout << (n - 1 + 3) % 12 + 1;
    return 0;
}

7-2 修剪灌木

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cout << max({i, 2 * (i - 1), 2 * (n - i)});
}

7-3 求和运算

重现赛中加了一个 1 0 5 10^5 105 的测试点,本来这题要考前缀和的,以为 1 0 4 10^4 104 的测试点能卡时间,没想到暴力也过了。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int a[N];
long long pr[N], sum;
int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        pr[i] = pr[i - 1] + a[i];
    }
    for (int i = 2; i <= n; i++)
        sum += a[i] * pr[i - 1];
    cout << sum;
    return 0;
}

7-4 合并数组

unique 对有序的数组进行去重,返回去重后的数组的end指针

#include <bits/stdc++.h>
using namespace std;
const int N = 20000 + 5;
int a[N];
int main() {
    int n, m;
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    cin >> m;
    for (int i = 0; i < m; i++)
        cin >> a[n + i];
    sort(a, a + n + m);
    int l = unique(a, a + n + m) - a;
    for (int i = 0; i < l; i++)
        cout << a[i] << " ";
    return 0;
}

7-5 骰子游戏

思路1:dfs深搜+剪枝,时间复杂度 O ( 6 m ) O(6^m) O(6m)

#include <bits/stdc++.h>
using namespace std;

int k, m, n, ans;

void dfs(int m, int s) {
    if (s > n)
        return;
    if (m == 0) {
        if (s == n)
            ans++;
        return;
    }
    for (int i = 1; i <= 6; i++)
        dfs(m - 1, s + i);
}
int main() {
    cin >> k;
    while (k--) {
        cin >> m >> n;
        ans = 0;
        dfs(m, 0);
        printf("%.2lf", ans / pow(6, m));
    }
}

思路2:用大量随机数模拟摇骰子的结果。因为在样本数足够大的情况下,可以用事件的频率来代替概率

#include <bits/stdc++.h>
using namespace std;

int k, m, n, ans;

bool randtest() {
    int res = 0;
    for (int i = 1; i <= m; i++)
        res += rand() % 6 + 1; // 生成[1,6]区间内的随机数
    return res == n;
}
int main() {
    cin >> k;
    while (k--) {
        cin >> m >> n;
        int ans = 0;
        for (int i = 1; i <= 1000000; i++)
            if (randtest())
                ans++;
        printf("%.2lf\n", ans / 1000000.0);
    }
}

7-6 字符串最大跨距

#include <bits/stdc++.h>
using namespace std;

int main() {
    string s, a, b;
    cin >> s;
    stringstream strin(s); // 使用字符串流去获取','分隔的字符串
    vector<string> res;
    while (getline(strin, s, ','))
        res.push_back(s);
    s = res[0], a = res[1], b = res[2];
    int p1 = s.find(a), p2 = s.rfind(b);
    if (p1 != -1 && p2 != -1)
        cout << p2 - (p1 + a.size());
    else
        cout << -1;
    return 0;
}

这题python的写法更优雅

s, a, b = input().split(',')
p1 = s.find(a)
p2 = s.rfind(b)
if p1 != -1 and p2 != -1:
    print(p2 - (p1 + len(a)))
else:
    print(-1)

7-7 上台阶

#include <bits/stdc++.h>
using namespace std;
long long f[200];
int main() {
    f[1] = 1;
    f[2] = 2;
    f[3] = 4;
    int n;
    cin >> n;
    for (int i = 4; i <= n; i++)
        f[i] = f[i - 1] + f[i - 2] + f[i - 3];
    cout << f[n];
}

7-8 A-B

#include <bits/stdc++.h>
using namespace std;
int main() {
    string a, b, ans;
    set<char> s;
    getline(cin, a);
    getline(cin, b);
    for (char c : b)
        s.insert(c);
    for (char c : a)
        if (!s.count(c))
            ans.push_back(c);
    cout << ans;
}

7-9 括号匹配

#include <bits/stdc++.h>
using namespace std;

map<char, char> mp;
string solve() {
    string s;
    cin >> s;
    stack<char> st;
    for (char c : s) {
        if (c == '(' || c == '[' || c == '{')
            st.push(c);
        else {
            if (st.empty()) {
                return "Extra right brackets";
            } else if (!st.empty() && mp[st.top()] == c) {
                st.pop();
            } else {
                return "Brackets not match";
            }
        }
    }
    if (st.size())
        return "Extra left brackets";
    else
        return "Brackets match";
}
int main() {
    mp['('] = ')';
    mp['['] = ']';
    mp['{'] = '}';
    cout << solve();
    return 0;
}

7-10 列出连通集

#include <bits/stdc++.h>
using namespace std;
const int N = 1000 + 5;
vector<int> G[N];
int vis[N];
int n, m, cnt;

void dfs(int u, int t) {
    if (vis[u])
        return;
    vis[u] = t;
    cout << u << " ";
    for (int v : G[u])
        dfs(v, t);
}
void bfs(int u, int t) {
    queue<int> Q;
    Q.push(u);
    while (!Q.empty()) {
        int u = Q.front();
        Q.pop();
        if (vis[u])
            continue;
        vis[u] = t;
        cout << u << " ";
        for (int v : G[u])
            Q.push(v);
    }
}
int main() {
    cin >> n >> m;
    while (m--) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    for (int u = 0; u < n; u++)
        sort(G[u].begin(), G[u].end()); // 按编号递增的顺序访问邻接点

    cnt = 0;
    memset(vis, 0, sizeof(vis));
    for (int u = 0; u < n; u++) {
        if (!vis[u]) {
            cout << "{ ";
            dfs(u, ++cnt);
            cout << "}\n";
        }
    }
    cnt = 0;
    memset(vis, 0, sizeof(vis));
    for (int u = 0; u < n; u++)
        if (!vis[u]) {
            cout << "{ ";
            bfs(u, ++cnt);
            cout << "}\n";
        }
}

7-12 哲哲打游戏

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int rec[N];
vector<int> choice[N];
int n, m;
int now = 1;
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        int k;
        cin >> k;
        choice[i].resize(k + 1);
        for (int j = 1; j <= k; j++)
            cin >> choice[i][j];
    }
    for (int i = 1; i <= m; i++) {
        int op, j; // op是option的缩写, not Genshin (雾
        cin >> op >> j;
        if (op == 0) {
            now = choice[now][j]; // 转移
        } else if (op == 1) {
            rec[j] = now; // 存档
            cout << now << endl;
        } else if (op == 2) {
            now = rec[j]; // 读档
        }
    }
    cout << now;
    return 0;
}

7-13 喊山

考试的时候想到用 Dijkstra 跑一遍最短路,把每条边权设置为1,超时了,但是运气好得了大部分分(22/25)

#include <bits/stdc++.h>
using namespace std;
using Edge = pair<int, int>;
const int N = 1e5 + 5, INF = 0x3f3f3f3f;

vector<Edge> G[N];
int dist[N];
bool vis[N];
int n, m, k;

void dijkstra(int s) {
    memset(vis, 0, sizeof(vis));
    memset(dist, 0x3f, sizeof(dist));
    dist[s] = 0;
    int maxdist = 0, idx = 0;
    while (true) {
        int u = -1, minv = INF;
        for (int i = 1; i <= n; i++)
            if (minv > dist[i] && !vis[i])
                u = i, minv = dist[i];
        if (u == -1)
            break;
        vis[u] = true;
        for (auto &[v, w] : G[u])
            if (dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                if (maxdist < dist[v]) {
                    maxdist = dist[v];
                    idx = v;
                } else if (maxdist == dist[v])
                    idx = min(idx, v);
            }
    }
    cout << idx << endl;
}
int main() {
    cin >> n >> m >> k;
    for (int i = 0, a, b; i < m; i++) {
        cin >> a >> b;
        G[a].push_back({b, 1});
        G[b].push_back({a, 1});
    }
    for (int i = 0, t; i < k; i++) {
        cin >> t;
        dijkstra(t);
    }
    return 0;
}

考完回来想到是不是可以用堆优化的Dijkstra,交一遍然后过了

#include <bits/stdc++.h>
using namespace std;
using Edge = pair<int, int>;
using Node = pair<int, int>;
const int N = 1e5 + 5, INF = 0x3f3f3f3f;

vector<Edge> G[N];
int dist[N];
int n, m, k;

void dijkstra(int s) {
    memset(dist, 0x3f, sizeof(dist));
    dist[s] = 0;
    int maxdist = 0, idx = 0;
    priority_queue<Node, vector<Node>, greater<Node>> q;
    q.push({0, s});
    while (!q.empty()) {
        auto [dist_u, u] = q.top();
        q.pop();
        if (dist[u] < dist_u)
            continue;
        for (auto &[v, w] : G[u])
            if (dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                q.push({dist[v], v});
                if (maxdist < dist[v]) {
                    maxdist = dist[v];
                    idx = v;
                } else if (maxdist == dist[v])
                    idx = min(idx, v);
            }
    }
    cout << idx << endl;
}
int main() {
    cin >> n >> m >> k;
    for (int i = 0, a, b; i < m; i++) {
        cin >> a >> b;
        G[a].push_back({b, 1});
        G[b].push_back({a, 1});
    }
    for (int i = 0, t; i < k; i++) {
        cin >> t;
        dijkstra(t);
    }
    return 0;
}

后面再去看大佬的提交,发现其实BFS就能跑出来。也想起来从哪里看的,边权相同的图,跑堆优化Dijkstra自动退化成BFS了

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, INF = 0x3f3f3f3f;

vector<int> G[N];
int dist[N];
int n, m, k;

void bfs(int s) {
    memset(dist, 0x3f, sizeof(dist));
    dist[s] = 0;
    int maxdist = 0, idx = 0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int v : G[u])
            if (dist[v] == INF) {
                dist[v] = dist[u] + 1;
                q.push(v);
                if (maxdist < dist[v]) {
                    maxdist = dist[v];
                    idx = v;
                } else if (maxdist == dist[v])
                    idx = min(idx, v);
            }
    }
    cout << idx << endl;
}
int main() {
    cin >> n >> m >> k;
    for (int i = 0, a, b; i < m; i++) {
        cin >> a >> b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    for (int i = 0, t; i < k; i++) {
        cin >> t;
        bfs(t);
    }
    return 0;
}

重新看来一遍最短路专题

问题边权算法时间复杂度
一个起点,一个终点非负数;无边权(或边权为1) A ∗ A^* A 算法 < O ( ( m + n ) log ⁡ n ) <O((m+n)\log n) <O((m+n)logn)
双向广搜 < O ( ( m + n ) log ⁡ n ) <O((m+n)\log n) <O((m+n)logn)
贪心最优搜索 < O ( m + n ) <O(m+n) <O(m+n)
一个起点到其他所有点无边权BFS O ( m + n ) O(m+n) O(m+n)
非负数Dijkstra;堆优化Dijkstra O ( n 2 ) O(n^2) O(n2) O ( ( m + n ) log ⁡ n ) O((m+n)\log n) O((m+n)logn)
允许有负数Bellman-Ford;SPFA < O ( m n ) <O(mn) <O(mn)
所有点对之间允许有负数Floyd-Warshall O ( n 3 ) O(n^3) O(n3)

暂时先写这些,后面再补充:)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

2023年第八届团队程序设计天梯赛选拔校赛(三)题解 的相关文章

随机推荐

  • ubuntu下make时对XX未定义的引用

    Q1 库对XX未定义的引用 xff0c 如 xff1a Thirdparty vio g2o lib libvio g2o so xff1a 对 39 IMUErrorModel lt ceres Jet lt double 38 gt g
  • Birch算法介绍

    目录 前言 一 Birch算法基本思想 二 聚类特征CF和CF 树 1 聚类特征CF 2 CF tree 3 CF tree 的生成 三 Birch算法流程 1 birch算法的优化 2 算法优缺点 四 算法实验实例 1 研究不指定簇数的情
  • [转]伪代码的写法

    伪代码的写法 xff08 附 xff1a 12种排序算法详解 xff09 转自 xff1a http blog sina com cn s blog 134451adb0102wfgu html 伪代码 xff08 Pseudocode x
  • linux C++调用python3的程序

    环境 xff1a ubuntu1404 python3 4 3 首先安装对应python不同版本的调用库 sudo apt get install python3 4 dev xff0c python脚本基本不用变 xff0c 在C 43
  • Bug 记录

    Bug记录 CocosCreator打包出现 Error xff1a Program type already present android support v4 os ResultReceiver MyResultReceiver 解决
  • I2C通信

    I2 C 芯片间 总线接口连接微控制器和串行 I 2 C 总线 它提供多主机功能 xff0c 控制所有 I 2 C 总线特定的 时序 协议 仲裁和定时 1 xff0c 物理层 1 IIC是一种两线串行的通信方式 xff0c SCL xff0
  • 使用Mybatis-Plus代码生成器的报错解决

    使用Mybatis Plus的同学 xff0c 在使用代码生成器的时候不知道有没有遇到过这个问题 xff1a 21 36 23 829 main DEBUG com baomidou mybatisplus generator AutoGe
  • Debian之安装完成后找不到命令解决办法

    1 修改配置文件 bashrc vim root bashrc export PATH 61 PATH usr sbin 2 使配置文件生效 source root bashrc
  • 相机标定、双目相机标定(原理)、三维重建效果展示

    1 相机标定的目的 xff1a xff08 1 xff09 通过单目相机标定分别求出左右相机的内参数和外参数 xff08 2 xff09 矫正由于镜头畸变造成的图片的变形 xff0c 例如 xff0c 现实中的直线 xff0c 拍摄成图像后
  • mac系统做openstack qcow2/raw镜像

    1 vmware安装出来虚拟机 xff08 操作系统不拆分 xff09 2 zhangjinyudeMacBook Pro Asianux vmwarevm zhangjinyu ls lh total 2820216 rw 1 zhang
  • 使用 Chrome 获取 Cookie 的数据

    Chrome 浏览器自带的开发功能相当强大 xff0c 这里只使用它的抓包功能 一 在浏览器中打开目标网站并登录 xff0c 进入目标页面 二 在 Chrome 浏览器下方的开发工具中单击 Network 标签页 按 F5 键 xff0c
  • 后台开发SQL技术总结

    一 字符串截取 1 substring str pos 用法 从字符串的第 4 个字符位置开始取 xff0c 直到结束 mysql gt select substring 39 example com 39 4 43 43 substrin
  • 论文记录:图像描述技术综述

    文章目录 前言 一 什么是image caption xff1f 二 基于深度学习的图像描述方法 1 基于编码器 解码器的方法 2 基于注意力机制的方法 3 基于生成对抗网络的方法 4 基于强化学习的方法 5 基于密集描述的方法 总结 前言
  • 一个接口有多个实现类

    如果一个接口有多个实现类 xff0c 在Controller层注入后调用 xff0c 怎么知道调用的是接口的哪个方法呢 xff1f 经过一番测试 和查找资料 终于找到了结果 2 0一个接口对应多个实现类 一个接口对应对个实现类 xff0c
  • c/c++使用libcurl库做http客户端及封装(HTTP_GET和HTTP_POST)

    由于项目需求需要发送http post去请求数据 xff0c 所以上网去寻找了一些发送http请求的方法 xff0c 发现libcurl较为常用 xff0c 然后根据官网上的例子 xff0c 对libcurl做了一些简单的封装 xff0c
  • (医学三维重建)MATLAB体绘制算法:多层面重建(MPR)

    xff08 医学三维重建 xff09 MATLAB体绘制算法 xff1a 多层面重建 xff08 MPR xff09 算法原理代码实现测试结果其他 by HPC ZY 算法原理 体绘制中比较特殊的一种 xff0c 因为它的输出是各种切面 就
  • Qt各个类之间继承关系

  • QGC -- 配置相机参数数据流说明(1)

    一 相关配置文件及对应画面 1 界面GeneralSettings qml 2 Video SettingsGroup json对应界面如下 xff1a span class token punctuation span span clas
  • ubuntu18.04 Intel Realsense T265与Realsense D435i 使用教程

    主要包括 xff1a realsense sdk驱动安装与ros包安装编译D435i与t256相机使用多个相机联合使用 官网链接 xff1a https github com IntelRealSense realsense roshttp
  • 2023年第八届团队程序设计天梯赛选拔校赛(三)题解

    文章目录 7 1 认识时钟7 2 修剪灌木7 3 求和运算7 4 合并数组7 5 骰子游戏7 6 字符串最大跨距7 7 上台阶7 8 A B7 9 括号匹配7 10 列出连通集7 12 哲哲打游戏7 13 喊山 标号标题分数提交通过率7 1