一维动态规划

[Algo] 一维动态规划

fx1 - 暴力递归, fx2 - 自顶向底动态规划(记忆化搜索), fx3 - 自底向顶动态规划(严格位置依赖)

1. 最低票价

// 1. 最低票价
// https://leetcode.cn/problems/minimum-cost-for-tickets/description/
int duration[3] = {1, 7, 30};
int f11(vector<int>& days, vector<int>& costs, int i){
    if (i == days.size()) return 0;
    int ans = INT32_MAX;
    for (int k = 0, j = i; k < 3; k++)
    {
        while (j < days.size() && days[j] < days[i] + duration[k]) j++;
        ans = min(ans, costs[k] + f11(days, costs, j));
    }
    return ans;
}
int f12(vector<int>& days, vector<int>& costs, int i, vector<int>& mem)
{
    if (i == days.size()) return 0;
    if (mem[i] != -1) return mem[i];
    int ans = INT32_MAX;
    for (int k = 0, j = i; k < 3; k++)
    {
        while (j < days.size() && days[j] < days[i] + duration[k]) j++;
        ans = min(ans, costs[k] + f12(days, costs, j, mem));
    }
    mem[i] = ans;
    return ans;
}
int f13(vector<int>& days, vector<int>& costs, vector<int>& dp)
{
    dp[dp.size() - 1] = 0;
    for (int i = days.size() - 1; i >= 0; i--)
    for (int k = 0, j = i; k < 3; k++)
    {
        while (j < days.size() && days[j] < days[i] + duration[k]) j++;
        dp[i] = min(dp[i], costs[k] + dp[j]);
    }
    return dp[0];
}
int mincostTickets(vector<int>& days, vector<int>& costs) {
    vector<int> dp(days.size() + 1, INT32_MAX);
    return f13(days, costs, dp);
}

2. 解码方法

// 2. 解码方法
// https://leetcode.cn/problems/decode-ways/
int f21(string &s, int i)
{
    if (i == s.length()) return 1;
    if (s[i] == '0') return 0;
    if (i + 1 < s.length() && (s[i] - '0') * 10 + s[i + 1] - '0' <= 26) return f21(s, i + 1) + f21(s, i + 2);
    else return f21(s, i + 1);
}
int f22(string &s, int i, vector<int> &mem)
{
    if (i == s.length()) return 1;
    if (mem[i] != -1) return mem[i];
    int ans;
    if (s[i] == '0') ans = 0;
    else ans = f22(s, i + 1, mem);
    if (s[i] != '0' && i + 1 < s.length() && (s[i] - '0') * 10 + s[i + 1] - '0' <= 26) ans += f22(s, i + 2, mem);
    mem[i] = ans;
    return ans;
}
int f23(string &s, vector<int> &dp)
{
    dp[dp.size() - 1] = 1;
    for (int i = s.size() - 1; i >= 0; i--)
    {
        if (s[i] == '0') dp[i] = 0;
        else dp[i] = dp[i + 1];
        if (s[i] != '0' && i + 1 < s.length() && (s[i] - '0') * 10 + s[i + 1] - '0' <= 26) dp[i] += dp[i + 2];
    }
    return dp[0];
}
int numDecodings(string s) {
    vector<int> dp(s.length() + 1);
    return f23(s, dp);
}

3. 最长有效括号串

// 3. 最长有效括号串
// https://leetcode.cn/problems/longest-valid-parentheses/description/
int longestValidParentheses(string s) {
    vector<int> dp(s.length());
    for (int i = 1; i < s.length(); i++)
    {
        if (s[i] == ')')
        {
            int p = i - dp[i - 1] - 1;
            if (p >= 0 && s[p] == '(') dp[i] = dp[i - 1] + 2 + (p - 1 >= 0 ? dp[p - 1] : 0);
        }
    }
    int ans = 0;
    for (int len : dp) ans = max(ans, len);
    return ans;
}
posted @ 2025-01-07 17:27  yaoguyuan  阅读(5)  评论(0)    收藏  举报