路径信息

[Algo] 路径信息

1. 最长公共子序列

// 1. 最长公共子序列
// https://www.nowcoder.com/practice/4727c06b9ee9446cab2e859b4bb86bb8
void dp1(string& s1, string& s2, vector<vector<int>>& dp) {
    int len1 = s1.length(), len2 = s2.length();
    for (int i = 1; i <= len1; i++)
        for (int j = 1; j <= len2; j++) {
            if (s1[i - 1] == s2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;
            else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
        }
}
string lcs(string& s1, string& s2) {
    int len1 = s1.length(), len2 = s2.length();
    vector<vector<int>> dp(len1 + 1, vector<int>(len2 + 1));
    dp1(s1, s2, dp); //构建动态规划表
    int length = dp[len1][len2], i = len1, j = len2;
    string ans;
    ans.resize(length);
    while (length > 0) {
        if (s1[i - 1] == s2[j - 1]) {
            ans[--length] = s1[i - 1];
            i--;
            j--;
        } else if (dp[i - 1][j] >= dp[i][j - 1]) {
            i--;
        } else {
            j--;
        }
    }
    return ans;
}

2. 最小的必要团队

// 2. 最小的必要团队
// https://leetcode.cn/problems/smallest-sufficient-team/
int dp2(vector<int> &people_skills, int n, int m, int i, int status, vector<vector<int>> &dp) {
    if (status == (1 << n) - 1) return 0;
    if (i == m) return INT32_MAX - 1;
    if (dp[i][status] != -1) return dp[i][status];

    int p1 = dp2(people_skills, n, m, i + 1, status, dp);
    int p2 = 1 + dp2(people_skills, n, m, i + 1, status | people_skills[i], dp);
    int ans = min(p1, p2);
    dp[i][status] = ans;
    return ans;
}
vector<int> smallestSufficientTeam(vector<string>& req_skills, vector<vector<string>>& people) {
    int n = req_skills.size(), m = people.size();
    unordered_map<string, int> skills_map;
    for (int i = 0; i < n; i++) skills_map[req_skills[i]] = i;
    vector<int> people_skills(m);
    for (int i = 0; i < m; i++) {
        int status = 0;
        for (int j = 0; j < people[i].size(); j++) {
            if (skills_map.count(people[i][j])) status |= 1 << skills_map[people[i][j]];
        }
        people_skills[i] = status;
    }
    vector<vector<int>> dp(m, vector<int>(1 << n, -1));
    int num = dp2(people_skills, n, m, 0, 0, dp); // 构建动态规划表

    vector<int> ans(num);
    int count = 0, status = 0, i = 0;
    while (count < num) {
        if (i != m - 1 && dp[i][status] == dp[i + 1][status]) i++;
        else {
            ans[count++] = i;
            status |= people_skills[i];
            i++;
        }
    }
    return ans;
}

3. 最长递增子序列

// 3. 最长递增子序列
// https://www.nowcoder.com/practice/30fb9b3cab9742ecae9acda1c75bf927
int find(vector<int> &ends, int len, int num) {
    int l = 0, r = len - 1, ans = -1;
    while (l <= r) {
        int m = (l + r) / 2;
        if (ends[m] >= num) {
            ans = m;
            r = m - 1;
        } else {
            l = m + 1;
        }
    }
    return ans;
}
int dp3(vector<int> &arr, vector<int> &dp) {
    int n = arr.size(), len = 0;
    vector<int> ends(n);
    for (int i = 0; i < n; i++) {
        int pos = find(ends, len, arr[i]);
        if (pos == -1) {
            ends[len++] = arr[i];
            dp[i] = len;
        } else {
            ends[pos] = arr[i];
            dp[i] = pos + 1;
        }
    }
    return len;
}
vector<int> lis(vector<int> &arr) {
    int n = arr.size();
    vector<int> dp(n);
    int len = dp3(arr, dp);
    vector<int> ans(len);
    for (int i = n - 1, cur = len; i >= 0; i--) {
        if (dp[i] == cur) {
            ans[cur - 1] = arr[i];
            cur--;
        }
    }
    return ans;
}
posted @ 2025-06-05 14:00  yaoguyuan  阅读(8)  评论(0)    收藏  举报