数字三角形问题
数字三角形问题是DP的经典入门问题
一共有三种计算方式:
直接递归计算(有一点回溯法的味道)
递推计算
记忆化搜索
其中记忆化搜索和直接递归计算非常的相似,只不过记忆化搜索将之前计算过的某些部分记录了下来,供以后使用。但是直接递归以前算过的依旧还是要算
下面贴上代码:
#include<cstdio> #include<cstdlib> #include<ctime> #include<algorithm> using namespace std; const int maxn = 100; int A[maxn][maxn]; int d[maxn][maxn]; int d1[maxn][maxn]; int n; //递推计算 int solve1() { for(int i = 1;i <= n;i++) { d[n][i] = A[n][i]; } for(int i = n - 1;i >= 1;i--) { for(int j = 1;j <= i;j++) { d[i][j] = max(d[i + 1][j],d[i + 1][j + 1]) + A[i][j]; } } return d[1][1]; } //记忆化搜索 int solve2(int i,int j) { if(d1[i][j] != -1)//在这个地方设置一个vis数组也是可以得 { return d1[i][j]; } if(i == n) { d1[i][j] = A[i][j]; return d[i][j]; } d1[i][j] = max(solve2(i + 1,j),solve2(i + 1,j + 1)) + A[i][j]; return d1[i][j]; } //完全递归计算 int solve(int i,int j) { if(i == n) { return A[i][j]; } else { return max(solve(i + 1,j),solve(i + 1,j + 1)) + A[i][j]; } } int main() { memset(d1,-1,sizeof(d1)); n = 26; for(int i = 1;i <= n ; i++) { for(int j = 1; j <= i;j++) { A[i][j] = rand()%10; } } printf("%d\n",solve(1,1)); printf("%lf\n",(double)clock()/CLOCKS_PER_SEC); printf("%d\n",solve1()); printf("%lf\n",(double)clock()/CLOCKS_PER_SEC); printf("%d\n",solve2(1,1)); printf("%lf\n",(double)clock()/CLOCKS_PER_SEC); }
在n = 26的时候,直接递推速度已经很慢了
但是在n = 100 的时候,递推和记忆话搜索还几乎不需要时间