牛客春招刷题训练营-2025.5.5题解

活动地址: 牛客春招刷题训练营 - 编程打卡活动

简单题 小红结账

按题意模拟计算。
向上取整可以将分子加上分母再减 ,再计算分子除以分母的向下取整。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<ll> a(m + 1);
    while (n--) {
        ll k, c;
        cin >> k >> c;
        for (int i = 0; i < k - 1; i++) {
            int x;
            cin >> x;
            a[x] += (c + k - 1) / k;
        }
    }
    for (int i = 1; i <= m; i++)cout << a[i] << ' ';
    return 0;
}

中等题 跳跃游戏(一)

为能到达的最远格子。
初值为

时,则 位置可到达,同时更新
最后判定

#include <bits/stdc++.h>
using namespace std;
int main() {
    int maxd = 1;
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)cin >> a[i];
    for (int i = 1; i <= n; i++)
        if (maxd >= i)
            maxd = max(maxd, i + a[i]);
    if (maxd >= n)
        cout << "true\n";
    else
        cout << "false\n";
    return 0;
}

困难题 郊区春游

状态压缩dp。
观察到 ,先用floyd求出任意两点间的最短路。
为状压方便,以下第 位等都以 开始。
表示游览状态为 ,最后一个游览第 个郊区的最小花费。
游览状态是什么?用 位二进制位表示状态,第 位为 表示第 个景区未被游览过,否则为被游览过。
初始状态:,否则为
枚举 为状态,从 为郊区,从
表示的状态中, 已被游览过且 未被游览过,就可以转移状态了。

判别 表示的状态中 的游览状态,可以将 右移 位并和 做按位与,结果为 则已游览过,否则未游览过。

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, m, R;
    cin >> n >> m >> R;
    vector<vector<int>> dis(n, vector<int>(n, 1e9));
    for (int i = 0; i < n; i++)
        dis[i][i] = 0;
    vector<int> V(R);
    for (int i = 0; i < R; i++)cin >> V[i];
    for (int i = 0; i < R; i++)V[i]--;
    while (m--) {
        int a, b, c;
        cin >> a >> b >> c;
        dis[a - 1][b - 1] = c;
        dis[b - 1][a - 1] = c;
    }
    for (int k = 0; k < n; k++)
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
    vector<vector<int>> dp(1 << R, vector<int>(R, 1e9));
    for (int i = 0; i < R; i++)
        dp[1 << i][i] = 0;
    for (int i = 0; i < (1 << R); i++) {
        for (int j = 0; j < R; j++) {
            for (int k = 0; k < R; k++) {
                if (j == k)continue;
                if ((((i >> j) & 1) == 1) && (((i >> k) & 1) == 0)) {
                    dp[i | (1 << k)][k] = min(dp[i | (1 << k)][k], dp[i][j] + dis[V[j]][V[k]]);
                }
            }
        }
    }
    cout << *min_element(dp[(1 << R) - 1].begin(), dp[(1 << R) - 1].end()) << '\n';
    return 0;
}
#牛客春招刷题训练营#
全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务