[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;
}