问题描述
在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的:
有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
已经告诉你了,这是个DP的题目,你能AC吗?
已经告诉你了,这是个DP的题目,你能AC吗?
1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
30
题目分析:简单的动态规划问题,代码如下:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int maps[102][102];
int dp[102][102]; //dp用来表示到当前行当前位置所累加的对大的数
int main()
{
int t;
cin >> t;
while(t--)
{
memset(maps,0,sizeof(maps));
memset(dp,0,sizeof(dp));
int n;
cin >> n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
cin >> maps[i][j];
}
}
dp[1][1]=maps[1][1];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
dp[i][j]=maps[i][j]+max(dp[i-1][j],dp[i-1][j-1]);
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
ans=max(ans,dp[i][j]);
}
}
cout << ans << endl ;
}
return 0;
}
也可以不使用dp数组来记录当前位置的和,从下往上开始记录,最后输出最顶上的值即可,代码如下:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,t;
cin>>t;
while(t--)
{
cin>>n;
int a[105][105];
for(int i=0;i<n;i++)
{
for(int j=0;j<i+1;j++)
cin>>a[i][j];
}
for(int i=n-2;i>=0;i--)
{
for(int j=0;j<i+1;j++)
{
if(a[i+1][j]>a[i+1][j+1]) a[i][j]=a[i][j]+a[i+1][j];
else a[i][j]=a[i][j]+a[i+1][j+1];
}
}
cout<<a[0][0]<<endl;
}
}