• 华为实验室研究岗社招机试题


    华为社招机试,面得实验室的研究岗,hr说是ACM难度的,诚不我欺

    第一题

    方法:最开始没有想到什么好方法,于是写个DFS,通过0%,后来加了一个最短路,没来得及测试。但是单独求最短路并没有考虑有多条最短路的情况。

    点击查看代码
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<map>
    #include<queue>
    using namespace std;
    
    struct Edge {
        int next, w;
    };
    
    const int maxn = 100+10;
    int n, m, t, s, e;
    int times[maxn], vals[maxn];
    vector<Edge>edges[maxn];
    
    Edge prenode[maxn], nxt[maxn];
    void dijsktra(int n, int s, int e) {
    
        vector<int> dist(n+1, INT_MAX);
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
        dist[s] = 0;
        pq.push({0, s});
        while(!pq.empty()) {
            int u = pq.top().second, d = pq.top().first;
            pq.pop();
            if(dist[u] < d) continue;   // 剪枝,已经求得更小的了
            if(u == e) break;
            for(auto& node : edges[u]) {
                int v = node.next, d = node.w;
                if(dist[v] > dist[u] + d) {
                    dist[v] = dist[u] + d;
                    prenode[v] = {u, d};
                    pq.push({dist[v], v});
                }
            }
        }
        int cur = e;
        while(cur != s) {
            nxt[prenode[cur].next] = {cur, prenode[cur].w};
            cur = prenode[cur].next;
        }
    
        while(cur != e) {
            cout << "cur: " << cur << endl;
            cur = nxt[cur].next;
        }
        cout << "cur: " << cur << endl;
    
        return;
    }
    
    /*
    4 4 22 0 3                     
    1 1  1 1
    5 7 9 12
    0 1 10
    0 2 10
    1 3 10
    2 3 10
    
    21
    */
    
    
    // 走到s点,还剩余时间t
    int maxval = -1;
    void dfs(int s, int t, int val, int pre) {
        cout << "dfs: " <<  s << " " << t << " " << val << endl;
        if(t < 0) return;
        // 该点不玩
        if(s == e) {
            if(t >= times[s]) val += vals[s];
            if(val > maxval) maxval = val;
            return;
        }
    
        int v = nxt[s].next, w = nxt[s].w;
        dfs(v, t-w, val, pre);
    
    
        // 该点完
        if(vals[s] < pre)  return;  // 大于前面的开心值才能玩
        t -= times[s];
        val += vals[s];
        dfs(v, t-w, val, vals[s]);
    }
    
    
    
    int main() {
        cin >> n >> m >> t >> s >> e;
        for(int i = 0; i < n; i++) {
            int tmp;
            cin >> tmp;
            times[i] = tmp;
        }
        for(int i = 0; i < n; i++) {
            int tmp;
            cin >> tmp;
            vals[i] = tmp;
        }
        for(int i = 0; i < m; i++) {
            int u, v, w;
            cin >> u >> v >> w;
            Edge e1 = {v, w};
            Edge e2 = {u, w};
            edges[u].push_back(e1);
            edges[v].push_back(e2);
        }
        dijsktra(n, s, e);
        dfs(s, t, 0, -1);
        cout << maxval << endl;
    }
    

    有一道类似题 D-景区路线规划 概率dp+dfs
    我觉得正解应该是Dijsktra变形+dp记忆化,优先队列中的节点 \([dist, id, time]\),类似于Leetcode 787. K 站中转内最便宜的航班

    补充:发现原题了https://izhen.me/2019/11/10/dp_graph/

    第二题

    题意:求最长的子串,且其最大值与最小值之差在\([m1, m2]\)内,如果有多个,输出子串和最大的

    方法:
    首先想到双指针,写法才发现不行,例如\(3 1 5 2, m1=3, m2=4\),双指针看到 \(3 1\) 时会发现不行然后就舍弃了,但是其实 \(3 1 5 2\) 这个整体是满足的
    类似的题是LC1438. 绝对差不超过限制的最长连续子数组,它相当于没有下界,左端点舍弃了就舍弃了,不会影响

    然后,只能暴力骗分了...,只通过了20%

    最后,枚举左端点\(i\),右端点\(j\)其实是可以二分得到的,因为\(j\)越大,最大值与最小值之差肯定也越大,具有单调性。
    但是这是带上下界的二分,且需要预处理区间最大最小值,需要用RMQ算法,,不想写。

  • 相关阅读:
    ACR Code Pacs
    如何利用IIS调试ASP.NET网站程序详解
    Server 2003 操作系统位数
    App.config/Web.config 中特殊字符的处理
    IE 对象不支持“attachEvent”属性或方法
    Invoke和BeginInvoke理解
    升级mongodb数据库2.6.6到3.0.3,切换引擎,主从同步数据
    mac android sdk manager 无法更新(被墙)
    hadoop-mongo map/reduce java
    mongodb use where and custom function to query mongodb存储过程
  • 原文地址:https://www.cnblogs.com/lfri/p/15740154.html
Copyright © 2020-2023  润新知