C++代码 dfs 搜素和优化后的记忆化搜素
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn = 1001;
int r, a[maxn][maxn], f[maxn][maxn];
int dfs0(int x, int y) // 提交超时
{
if(x==r-1)
{
return a[x][y];
}
return max(dfs0(x+1, y), dfs0(x+1, y+1))+a[x][y];
}
int dfs(int x, int y) // 记忆化搜索 x为行,y为列
{
if (f[x][y] >= 0)
return f[x][y]; // 如果这个数算过就直接返回,不用再一次计算
if (x == r-1)
f[x][y] = a[x][y]; // 如果到了最后一行,就直接赋值,因为没有下一行无法判断
else
f[x][y] = max(dfs(x + 1, y), dfs(x + 1, y + 1)) + a[x][y]; // 把下一行较大的数与这一个数相加
return f[x][y];
}
int main()
{
scanf("%d", &r);
for (int i = 0; i < r; i++)
for (int j = 0; j <= i; j++)
scanf("%d", &a[i][j]);
// int ans = dfs0(0, 0);
// std::cout << ans << std::endl;
memset(f, -1, sizeof(f)); // 此处把f全都定义成-1,是因为金字塔里面的数有可能也是0,这样就更容易判断
cout << dfs(0, 0) << endl;
return 0;
}
c++ 代码:顺推, 逆推, 实际就是动态规划
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1001;
int r, a[maxn][maxn];
int shuntui()
{
int ans = 0;
int x, y;
for (x = 1; x < r; x++) // 向下逐层累加
for (y = 0; y <= x; y++){
if (y == 0)
a[x][y] += a[x - 1][y];
else
a[x][y] += max(a[x - 1][y - 1], a[x - 1][y]);
}
for (x = 0; x < r; x++) // 最后一行找出最大值
ans = max(ans, a[r-1][x]);
return ans;
}
int nitui()
{
int x, y;
for (x = r-2; x >= 0; x--) // 向上逐层累加
for (y = 0; y <= x; y++)
a[x][y] += max(a[x+1][y],a[x+1][y+1]);
return a[0][0];
}
int main()
{
scanf("%d", &r);
for (int i = 0; i < r; i++)
for (int j = 0; j <= i; j++)
scanf("%d", &a[i][j]);
cout << nitui() << endl;
return 0;
}
总结: 依次思索这个几种解法可以了解动态规划思想的产生过程,先是暴力递归,再是记忆化递归(相当于大量剪枝递归树),然后是动态规划,从顺推到逆推,就是为了更好的动态规划。
参考链接:
[2]动态规划详解(修订版)