优化枚举

[Algo] 优化枚举

1. 买卖股票的最佳时机 III

// 1. 买卖股票的最佳时机 III
// https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/
int maxProfit(vector<int>& prices) {
    int n = prices.size();
    vector<int> dp1(n); // dp1[i]: 0...i范围内买卖第一次股票能够获得的最大收益
    for (int i = 1, min_price = prices[0]; i < n; i++) {
        min_price = min(min_price, prices[i]);
        dp1[i] = max(dp1[i - 1], prices[i] - min_price);
    }
    vector<int> best(n);
    best[0] = dp1[0] - prices[0];
    for (int i = 1; i < n; i++) {
        best[i] = max(best[i - 1], dp1[i] - prices[i]);
    }
    vector<int> dp2(n); // dp2[i]: 在第i天第二次卖股票能够获得的最大总收益
    int ans = 0;
    for (int i = 1; i < n; i++) {
        dp2[i] = best[i] + prices[i];
        ans = max(ans, dp2[i]);
    }
    return ans;
}

2. 买卖股票的最佳时机 IV

// 2. 买卖股票的最佳时机 IV
// https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/
int free(vector<int>& prices) {
    int ans = 0, n = prices.size();
    for (int i = 1; i < n; i++) {
        ans += max(0, prices[i] - prices[i - 1]);
    }
    return ans;
}
int maxProfit(int k, vector<int>& prices) {
    int n = prices.size();
    if (k >= n / 2) {
        return free(prices);
    }
    vector<vector<int>> dp(k + 1, vector<int>(n)); // dp[i][j]: 在0...j范围内买卖股票i次能够获得的最大收益
    for (int i = 1; i <= k; i++) {
        int best = dp[i - 1][0] - prices[0];
        for (int j = 1; j < n; j++) {
            best = max(best, dp[i - 1][j] - prices[j]);
            dp[i][j] = max(dp[i][j - 1], best + prices[j]);
        }
    }
    return dp[k][n - 1];
}

3. 买卖股票的最佳时机含手续费

// 3. 买卖股票的最佳时机含手续费
// https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/
int maxProfit(vector<int>& prices, int fee) {
    int n = prices.size();
    int prepare = -prices[0] - fee; // prepare : 交易次数无限制情况下,获得收益的同时扣掉了一次购买和手续费之后,最好的情况
    int done = 0; // done : 交易次数无限制情况下,能获得的最大收益
    for (int i = 1; i < n; i++) {
        int tmp = done;
        done = max(done, prepare + prices[i]);
        prepare = max(prepare, tmp - prices[i] - fee);
    }
    return done;
}

4. 买卖股票的最佳时机含冷冻期

// 4. 买卖股票的最佳时机含冷冻期
// https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/
int maxProfit(vector<int>& prices) {
    int n = prices.size();
    if (n < 2) return 0;
    vector<int> prepare(n); // prepare[i]: 0...i范围内交易次数无限制情况下,获得收益的同时扣掉了一次购买之后,最好的情况
    vector<int> done(n); // done[i]: 0...i范围内交易次数无限制情况下,能获得的最大收益
    prepare[1] = max(-prices[0], -prices[1]);
    done[1] = max(0, prices[1] - prices[0]);
    for (int i = 2; i < n; i++) {
        done[i] = max(done[i - 1], prepare[i - 1] + prices[i]);
        prepare[i] = max(prepare[i - 1], done[i - 2] - prices[i]);
    }
    return done[n - 1];
}

5. DI序列的有效排列

// 5. DI序列的有效排列
// https://leetcode.cn/problems/valid-permutations-for-di-sequence/
int func1(string& s, int cur, int less, vector<vector<int>>& dp) {
    int n = s.length() + 1;
    if (cur == n) return 1;
    if (dp[cur][less] != -1) return dp[cur][less];
    int ans = 0;
    if (cur == 0 || s[cur - 1] == 'D') {
        for (int nextLess = 0; nextLess < less; nextLess++) {
            ans = (ans + func1(s, cur + 1, nextLess, dp)) % MOD;
        }
    } else {
        for (int nextLess = less; nextLess < n - cur; nextLess++) {
            ans = (ans + func1(s, cur + 1, nextLess, dp)) % MOD;
        }
    }
    dp[cur][less] = ans;
    return ans;
}
int func2(string& s) {
    int n = s.length() + 1;
    vector<vector<int>> dp(n + 1, vector<int>(n + 1));
    for (int i = 0; i <= n; i++) dp[n][i] = 1;
    for (int i = n - 1; i >= 0; i--) {
        for (int j = 0; j <= n; j++) {
            if (i == 0 || s[i - 1] == 'D') {
                for (int k = 0; k < j; k++) {
                    dp[i][j] = (dp[i][j] + dp[i + 1][k]) % MOD;
                }
            } else {
                for (int k = j; k < n - i; k++) {
                    dp[i][j] = (dp[i][j] + dp[i + 1][k]) % MOD;
                }
            }
        }
    }
    return dp[0][n];
}
int func3(string& s) {
    int n = s.length() + 1;
    vector<vector<int>> dp(n + 1, vector<int>(n + 1));
    for (int i = 0; i <= n; i++) dp[n][i] = 1;
    for (int i = n - 1; i >= 0; i--) {
        if (i == 0 || s[i - 1] == 'D') {
            dp[i][1] = dp[i + 1][0];
            for (int j = 2; j <= n; j++) {
                dp[i][j] = (dp[i][j - 1] + dp[i + 1][j - 1]) % MOD;
            }
        } else {
            dp[i][n - i - 1] = dp[i + 1][n - i - 1];
            for (int j = n - i - 2; j >= 0; j--) {
                dp[i][j] = (dp[i][j + 1] + dp[i + 1][j]) % MOD;
            }
        }
    }
    return dp[0][n];
}
int numPermsDISequence(string s) {
    return func3(s);
}
posted @ 2025-03-28 10:51  yaoguyuan  阅读(11)  评论(0)    收藏  举报