lc442

lc442

链接

1

题目大意

有一个 \(n X n\) 的网格,每个格子可以装一个重量 恰好\(w\) 的箱子,总重量不能超过 \(max\)

返回可以装到船上的 最大 箱子数量。

思路

如果没有 \(n\) 的限制,最多可以装的箱子数是 \(max / w\) ,但是总个数要小于等于 \(n * n\),所以它们取 \(min\)

代码

class Solution {
public:
    int maxContainers(int n, int w, int ma) {
        int res = n * n;
        int u = ma / w;
        return min(u, res);
    }
};

2

题目大意

有一个 \(n X m\) 二维整数数组 \(p\),以及一个整数 \(k\)

定义一个函数 \(intersect(a, b)\),它返回b数组 \(a\)\(b\)相同数字的种类个数

构造一个 无向图,其中每个索引 i 对应 p[i]。如果且仅当 intersect(p[i], p[j]) >= k(其中 i 和 j 的范围为 [0, n - 1] 且 i != j),节点 i 和节点 j 之间有一条边。

返回结果图中 连通分量 的数量。

思路

要求连通分量的数量,那么一个节点属于一个连通块之后,就不可能属于另一个连通块,所以在一个点被遍历之后就不能继续遍历

在写inter函数寻找相同元素的种类时为了避免多次计算,可以找到一个之后,就把它从被寻找的数组中删除

建图的时候,直接将不同元素种类的下标放在当前下标的数组中,形成对应关系

最后再一个一个遍历

代码

class Solution {
public:
    int inter(vector<int>& a, vector<int>& b) {
        unordered_set<int> res(a.begin(), a.end()), ans;
        int cu = 0;
        for(auto& u : b) {
            if(res.count(u)) {
                res.erase(u); //防止重复
                cu++;
            }
        }
        return cu;
    }

    int numberOfComponents(vector<vector<int>>& g, int k) {
        int n = g.size(), m = g[0].size();
        vector<int> st(110);
        int cnt = 0;
        vector<int> d[110];
        for(int i = 0; i < n; i++) {
            for(int j = i + 1; j < n; j++) {
                if(inter(g[i], g[j]) >= k) d[i].push_back(j), d[j].push_back(i);
            }
        }
        function<void(int)> dfs = [&](int x) {
            st[x] = 1;
            for(auto& u : d[x]) {
                if(!st[u]) dfs(u);
            }
        };
        for(int i = 0; i < n; i++) {
            if(!st[i]) {
                dfs(i);
                cnt++;
            }
        }
        return cnt;
    }
};

3

题目大意

给你两个长度分别为 \(n\)\(m\) 的整数数组 \(q\)\(w\)

在一个实验室里,有 \(n\) 个巫师,他们必须按顺序酿造 \(m\) 个药水。每个药水的法力值为 \(w[j]\)并且每个药水 必须 依次通过 所有 巫师处理,才能完成酿造。第 i 个巫师在第 j 个药水上处理需要的时间为 \(time = q[i] * w[j]\)

药水在当前巫师完成工作后 必须 立即传递给下一个巫师并开始处理。这意味着每个巫师在药水到达时 马上 开始工作。

返回酿造所有药水所需的 最短 总时间。

思路

  • 巫师要完成当前这瓶药水的 前提前一个巫师已经完成这瓶 并且 这个巫师已经完成上一瓶药水 -- 正推实现

  • 保证时间连续,就要从最后一个巫师来倒推,倒数第二个巫师的完成时间,就是最后一个巫师的时间减去酿造时间 -- 倒推实现

代码

1)

class Solution {
public:
    using ll = long long;
    long long minTime(vector<int>& q, vector<int>& w) {
        int n = q.size(), m = w.size();
        vector<ll> s(n);
        for(int i = 0; i < m; i++) {
            ll u = 0; //u表示的就是前一个巫师的完成时间
            for(int j = 0; j < n; j++) {
               u = max(u, s[j]) + q[j] * w[i]; //这里s[j]表示的是第j个巫师完成上一瓶药水的时间,取最大值,确保都完成
            }
            s[n - 1] = u;

            //倒推使得时间连续
            for(int j = n - 2; j >= 0; j--) {
                u -= q[j + 1] * w[i];
                s[j] = u;
            }
        }
        return s[n - 1];
    }
};

2)

class Solution {
public:
    using ll = long long;
    long long minTime(vector<int>& q, vector<int>& w) {
        int n = q.size(), m = w.size();
        vector<ll> f(n + 2);
        for(int i = 1; i <= m; i++) {
            //正推
            for(int j = 1; j <= n; j++) {
                f[j] = max(f[j - 1], f[j]) + q[j - 1] * w[i - 1];
            }
            //倒推
            for(int j = n - 1; j > 0; j--) {
                f[j] = f[j + 1] - q[j] * w[i - 1];
            }
        }
        return f[n];
    }
};
posted @ 2025-03-23 18:32  PeachyGalaxy  阅读(11)  评论(0)    收藏  举报