4-7笔试记录

第一题:
幼儿园老师安排小朋友做游戏,现在需要给N为小朋友进行分组,老师想让每个同学写一个名字,代表这位小朋友想和谁分到一组,请问老师在满足所有小朋友意愿的情况下,最多可以将班级分成多少组?
输入描述:
第一行输入N, 0 < N <= 100000
接下来是N行代表每个小朋友希望和谁分到一组,如“John Jack ”,代表John希望和Jack分到一组,两个名字之间以空格分割,名字本身不存在空格
输出描述:
分组的最多数量
例1:
6
Jack Tom
Alice John
Jessica Leonie
Tom Alice
John Jack
Leonie Jessica
2

例2:
6
Jack Tom
Alice John
Jessica Tom
Tom Alice
John Jack
Leonie Jessica
1

例3:
3
Xiaoming Xiaohong
Xiaohong Xiaoqiang
Xiaoqiang Xiaoming
1

并查集(LeetCode 547省份的数量)

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
using namespace std;

class DisjointSet{
public:
    DisjointSet(int n) :parent(vector<int>(n)), rank(vector<int>(n)), count(n) {
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }

    int find(int x) {
        if (x != parent[x]) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }

    void merge(int x, int y) {
        int rootx = find(x);
        int rooty = find(y);
        if (rootx == rooty) {
            return;
        }
        if (rootx != rooty) {
            if (rank[rootx] < rank[rooty]) {
                swap(rootx, rooty);
            }
            parent[rooty] = rootx;
            if (rank[rootx] == rank[rooty]) rank[rootx] += 1;
        }
        count--;
    }

    int getCount() {
        return count;
    }

private:
    vector<int> parent;
    vector<int> rank;
    int count;
};

int main() {
    int n;
    cin >> n;
    DisjointSet disjoint_set(n);

    vector<string> s1;
    vector<string> s2;
    string name;
    int result = 0;
    while (n--) {
        cin >> name;
        s1.push_back(name);
        cin >> name;
        s2.push_back(name);
    }

    unordered_map<string, int> umap;
    for (int i = 0; i < s1.size(); i++) {
        umap[s1[i]] = i;
    }

    for (int i = 0; i < s1.size(); i++) {
        disjoint_set.merge(umap[s1[i]], umap[s2[i]]);
    }
    cout << disjoint_set.getCount() << endl;
    system("pause");
    return 0;
}

第二题:
给定N个任务(1 <= N <=100),任务编号从0开始顺序累加,这N个任务在系统中排队顺序执行,每个任务的自身执行时间为非负数,依次为t1,t2,...tn。部分任务之间存在依赖关系,某任务所依赖的任务如果没有执行,则该任务需要重回对尾重新排队。只有任务执行以及任务排队等待消耗时间,其余操作消耗时间忽略不计。请计算每个任务的实际执行时间(实际执行时间 = 任务自身执行的时间 + 在队列中等待其他任务执行的时间)

输入描述:
第一行输入按照任务编号递增的顺序表示N个任务的自身执行时间,为逗号分隔的字符串,执行时间取值范围[1,999]。例如:1,3,4(逗号前后没有空格)。第二行为循环依赖关系如0 —>2,表示0号任务的执行依赖2好任务的执行。
输出描述:
按照任务编号递增的顺序,输出每个任务的实际执行时间。以逗号为分隔,逗号前后不要有空格,例如:8, 3, 7
实例1:
输入:
1,3,4
0—>2
输出:
8, 3, 7

说明:
输入参数中的依赖关系通过任务序号表示,例如0—>2, 表示0号任务的执行依赖2好任务的执行,输出为每个任务的实际消耗时间,顺序和输入的任务顺序一致。

实例2:
输入:
1,3,4,5,8,5,3,6
0—>2,2—>4,2—>6
输出:
35,3,34,8,16,21,24,30

拓扑排序(LeetCode207课程表)

#include <iostream>
#include <queue>
#include <string>
#include <sstream>
using namespace std;

int main() {
    string s;
    string t;
    cin >> s;
    stringstream ss(s);
    // 将任务编号与时间构造为pair插入到队列当中
    queue<pair<int,int>> que;
    int i = 0;
    while (getline(ss, t, ',')){
        que.push(pair<int,int>(i++, stoi(t)));
    }
    // 计算边的依赖关系和每个任务的入度
    vector<vector<int>> edges(que.size());
    vector<int> indeg(que.size(),0);
    cin >> s;
    stringstream input(s);
    while (getline(input, t, ',')) {
        edges[t[3] - '0'].push_back(t[0] - '0');
        indeg[t[0] - '0']++;
    }
    // 模拟任务队列执行
    vector<int> result(que.size(), 0);
    int time = 0;
    while (!que.empty()) {
        pair<int, int> u = que.front();
        que.pop();
        if (indeg[u.first] == 0) {
            time += u.second;
            result[u.first] = time;
            // 如果任务成功执行,将依赖于该任务的节点入度减一
            for (auto v : edges[u.first]) {
                --indeg[v];
            }
        }
        else {
            que.push(u);
        }
    }
    // 输出结果
    for (int i = 0; i < result.size() - 1; i++) {
        cout << result[i] << ',';
    }
    cout << result[result.size() - 1] << endl;

    system("pause");
    return 0;
}

第三题:
到香港旅游,最后一站决定去迪士尼乐园打卡,因为返程机票已经订好,所以我们必须在剩余可游玩时间t分钟内完成游玩,才能不耽误行程,请你为我们设计一条最佳游玩路线,选择规则如下:
1、游玩总时长不能超过t,但最接近t
2、游玩时不想走回头路,仅向右或向下两个方向,畅玩到出口
乐园被划分为一个row*col的风格区域地图,在每个方格区域上,标注了游玩的最佳时长,从入园口[0,0]出发,选定最佳游玩路线,一路畅玩到出口[row-1,col-1]

输入描述:
首行输入以单个空格分割的三个正整数row和col以及t,row代表地图行数(0 < row <=13),col代表地图列数(0 < col <= 13),t代表剩余可游玩时间(0 < t <= 600):
接下来row行,每一行包括col个以单个空格分割的数字,代表该方格区域最佳游玩时长time分钟(0 < time < 100)
输出描述:
最佳游玩线路游玩总时长,若不存在,请输出-1

例1
5 5 30
3 5 4 2 3
4 5 3 4 3
4 3 5 3 2
2 5 3 3 5
5 3 4 4 1
输出
30
一种可能的游玩路线是[0,0]—>[1,0]—>[2,0]—>[3,0]—>[4,0]—>[4,1]—>[4,2]—>[4,3]—>[4,4],刚好30分钟玩完整个项目,剩余时间可玩时间t没有任何偏差,因此输出30

例2
5 5 10
3 5 4 2 3
4 5 3 4 3
4 3 5 3 2
2 5 3 3 5
5 3 4 4 1
输出-1
说明:
无论走哪条路线,其游玩时间都会超过剩余可玩时间t,因此输出-1

三维DP

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n, m, t;
    cin >> n >> m >> t;
    vector<vector<int>> grid(n, vector<int>(m, 0));
    int temp;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> temp;
            grid[i][j] = temp;
        }
    }
    // 先用一个2维DP求出到达每个点有多少种路径  LeetCode 62题 不同路径
    vector<vector<int>> dp(n, vector<int>(m, 0));
    for (int i = 0; i < n; i++) {
        dp[i][0] = 1;
    }
    for (int j = 0; j < n; j++) {
        dp[0][j] = 1;
    }
    for (int i = 1; i < n; i++) {
        for (int j = 1; j < m; j++) {
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        }
    }
    // 初始化一个3维DP数组,dp[i][j][k]的含义经过不同路径达该点处的时间
    int q = dp[n - 1][m - 1];
    vector<vector<vector<int>>> dpq(n, vector<vector<int>>(m, vector<int>(q, 0)));
    dpq[0][0][0] = grid[0][0];
    for (int i = 1; i < n; i++) {
        dpq[i][0][0] = dpq[i - 1][0][0] + grid[i][0];
    }
    for (int j = 1; j < n; j++) {
        dpq[0][j][0] = dpq[0][j - 1][0] + grid[0][j];
    }

    for (int i = 1; i < n; i++) {
        for (int j = 1; j < m; j++) {
            int p = 0;
            for (int k = 0; k < dp[i- 1][j]; k++) {
                dpq[i][j][k] = dpq[i - 1][j][k] + grid[i][j];
                p++;
            }
            for (int k = 0; k < dp[i][j - 1]; k++) {
                dpq[i][j][k + p] = dpq[i][j - 1][k] + grid[i][j];
            }
        }
    }
    // 将dpq[n - 1][m - 1]中大于t的值全部置0
    int result = 0;
    for (int i = 0; i < q; i++) {
        if (dpq[n - 1][m - 1][i] > t) {
            dpq[n - 1][m - 1][i] = 0;
        }
    }
    // 求剩余值中的最大值
    for (int i = 0; i < q; i++) {
        if (dpq[n - 1][m - 1][i] > result) {
            result = dpq[n - 1][m - 1][i];
        }
    }

    // 如果求得最大值则返回,如果没有则返回-1
    if (result != 0) {
        cout << result << endl;
    }
    else {
        cout << -1 << endl;
    }

    system("pause");

    return 0;
}
全部评论

相关推荐

11-03 14:38
重庆大学 Java
AAA求offer教程:我手都抬起来了又揣裤兜了
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务