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];
    }
};
                    
                
                
            
        
浙公网安备 33010602011771号