C/C++教程

AcWing第8场周赛题解

本文主要是介绍AcWing第8场周赛题解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

A. 3770. 最小消耗

题目链接:https://www.acwing.com/problem/content/description/3773/

题目大意:按照题目要求消灭两种类型怪兽(可以消耗 c 转换)的最小消耗。

解题思路:循环记录 0 和 1 出现的次数,消灭一个 0 的最小消耗为 min(a, b+c),消灭一个 1 的最小消耗为 min(a+c, b)

示例程序:

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

int T, n, a, b, c, c0, c1;
char s[1010];

int main() {
    cin >> T;
    while (T--) {
        cin >> n >> a >> b >> c >> s;
        c0 = c1 = 0;
        for (int i = 0; i < n; i++)
            (s[i] == '0') ? c0++ : c1++;
        cout << c0 * min(a, b+c) + c1 * min(a+c, b) << endl;
    }
    return 0;
}

B. AcWing 3771. 选取石子

题目链接:https://www.acwing.com/problem/content/3774/

题目大意:从数列里面选出一些数满足 \(a_i - a_j = i - j\)。

解题思路:将所有 \(a_i\) 放入 \(a_i - i\) 的桶中(实际实现时用的 map),找最大的那个桶。

示例程序:

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

map<int, long long> mp;
int n, a;
long long ans;

int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a;
        mp[a-i] += a;
    }
    for (auto p : mp)
        ans = max(ans, p.second);
    cout << ans << endl;
    return 0;
}

C. 3772. 更新线路

题目链接:https://www.acwing.com/problem/content/3775/

题目大意:求一条路径走过来最短路最少和最多更新次数。

解题思路:返图+最短路+最短路计数。最少更新次数是不是最短路径的点,最多更新次数是:不是最短路径的点+最短路径不唯一的点。由于边权为 \(1\),所以可以 bfs 求最短路。注意:强连通图的条件很重要,这能保证反图也强连通。

最主要的逻辑在第 40 ~ 42 行。请认真体会(调了好长时间)

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int n, m, k, p[maxn], dis[maxn], cnt[maxn], pre[maxn];
vector<int> g[maxn];
queue<int> que;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> n >> m;
    while (m--) {
        int u, v;
        cin >> u >> v;
        g[v].push_back(u); // 建反图
    }
    cin >> k;
    for (int i = 1; i <= k; i++) cin >> p[i];
    memset(dis, -1, sizeof(int)*(n+1));
    dis[p[k]] = 0;
    cnt[p[k]] = 1;
    que.push(p[k]);
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        for (auto v : g[u]) {
            if (dis[v] == -1) {
                dis[v] = dis[u] + 1;
                cnt[v] = 1;
                pre[v] = u;
                que.push(v);
            }
            else if (dis[v] == dis[u] + 1)
                cnt[v]++;
        }
    }
    int c1 = 0, c2 = 0;
    for (int i = 1; i <= k; i++) {
        int u = p[i];
        if (i < k && cnt[u]==1 && pre[u] == p[i+1]) continue; // 新增条件:非最短路但是不唯一也不更新
        if (i < k && dis[u] != dis[p[i+1]] + 1) c1++;
        if (cnt[u] > 1 || i < k && pre[u] != p[i+1]) c2++;
    }
    cout << c1 << " " << c2 << endl;
    return 0;
}
这篇关于AcWing第8场周赛题解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!