基础的动态规划问题
懂得如何递归加上记忆便轻松解决
代码如下:
#include <iostream>
using namespace std;
int Road(int i,int j);
int Max(int a,int b);
int n;
int D[105][105];
int dp[105][105];
int main()
{
int i,j;
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=i;j++)
{
cin>>D[i][j];
dp[i][j]=-1;
}
cout<<Road(1,1)<<endl;
return 0;
}
int Road(int i,int j)
{
if(dp[i][j]!=-1) return dp[i][j];
if(i==n) return D[i][j];
return dp[i][j]=Max(Road(i+1,j),Road(i+1,j+1))+D[i][j];
}
int Max(int a,int b)
{
if(a>b) return a;
else return b;
}
}
但是,就这样结束了吗?
记忆性递归归根到底还是递归的方法,不可避免的问题就是递归次数过度导致栈溢出。
那么如何解决这个问题?很简单,有递归转化为递推。
从最低层往上推
首先需要计算的是最后一行,因此可以把最后一行直接写出,现在开始分析倒数第二行的每一个数,现分析数字2,2可以和最后一行4相加,也可以和最后一行的5相加,但是很显然和5相加要更大一点,结果为7,我们此时就可以将7保存起来,然后分析数字7,7可以和最后一行的5相加,也可以和最后一行的2相加,很显然和5相加更大,结果为12,因此我们将12保存起来。
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
int D[105][105];
int maxSum[105][105];
int main()
{
int i,j,n;
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=i;j++)
cin>>D[i][j];
for(i=1;i<=n;i++)
maxSum[n][i]=D[n][i];
for(i=n-1;i>=1;i--)
for(j=1;j<=i;j++)
maxSum[i][j]=max(maxSum[i+1][j],maxSum[i+1][j+1])+D[i][j];
cout<<maxSum[1][1]<<endl;
return 0;
}
显然简单了许多。