动态规划篇——记忆化搜索与递推
1.动态规划篇——记忆化搜索与递推
2.动态规划篇——背包问题-
记忆化搜索与递推
定义
在使用动态规划的时候,我们可能会对某些状态进行重复访问。实际上,我们可以通过存储访问数据的方式,避免重复访问某些状态时的重复计算,达到在时间上优化算法的目的。
例题
【例 1】 Function
【例 2】 三倍经验
例题分析
【例 1】
分析
这近乎是一道裸的 DP (橙题能有什么弯)。但是,如果使用最朴素的 DP,递归的次数将会非常多。
所以,我们要引入记忆化数组,将递归过程中得到的信息储存。再次访问这些数据时,就能避免重复递归(这是一种空间换时间的思想)。
代码
#include <iostream> using namespace std; long long remember[25][25][25]; long long w(long long a, long long b, long long c) { if (a <= 0 || b <= 0 || c <= 0) { a = 0; b = 0; c = 0; } if (a > 20 || b > 20 || c > 20) { a = 20; b = 20; c = 20; } if (remember[a][b][c]) { return remember[a][b][c]; } else { if (a <= 0 || b <= 0 || c <= 0) { remember[a][b][c] = w(0, 0, 0); } else if (a > 20 || b > 20 || c > 20) { remember[a][b][c] = w(20, 20, 20); } else if (a < b && b < c) { remember[a][b][c] = w(a, b, c - 1) + w(a, b - 1, c - 1) - w(a, b - 1, c); } else { remember[a][b][c] = w(a - 1, b, c) + w(a - 1, b - 1, c) + w(a - 1, b, c - 1) - w(a - 1, b - 1, c - 1); } return remember[a][b][c]; } } int main() { long long a, b, c; remember[0][0][0] = 1; while (cin >> a >> b >> c) { if (a == -1 && b == -1 && c == -1) { break; } else { cout << "w(" << a << ", " << b << ", " << c << ") = "; cout << w(a, b, c) << endl; } } return 0; }
【例 2】
分析
首先,如果没有“同时作为一个强大的小朋友,你可以选择金字塔中的不多于
对于这个简化的问题,我们作如下分析:每个点的“来路”为其左上与右上的点,那么我们只需要设
其中
回到本题。本题的难点即在我们可以选择不多于
最后我们只需要在所有的
代码
#include <iostream> #define int long long using namespace std; int dp[105][105][105];//dp[i][j][k]表示在第i行第j列,使用k次能力之后的最大值 int a[105][105]; signed main() { int n, _k; cin >> n >> _k; for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++)cin >> a[i][j]; } for (int i = 0; i <= 100; i++) { for (int j = 0; j <= 100; j++) { for (int k = 0; k <= 100; k++)dp[i][j][k] = -1e10; } } dp[1][1][0] = a[1][1]; dp[1][1][1] = 3 * a[1][1]; for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { for (int k = 0; k <= min(_k, i); k++) { dp[i][j][k] = max(dp[i][j][k], max(dp[i - 1][j][k] + a[i][j], dp[i - 1][j - 1][k] + a[i][j])); dp[i][j][k + 1] = max(dp[i][j][k + 1], max(dp[i - 1][j][k] + 3 * a[i][j], dp[i - 1][j - 1][k] + 3 * a[i][j])); } } } int ans = dp[n][1][0]; for (int j = 1; j <= n; j++) { for (int k = 0; k <= min(_k, n); k++) { ans = max(ans, dp[n][j][k]); } } cout << ans << endl; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探