1454: 数字三角形
时间限制: 1 Sec 内存限制: 128 MB提交: 15 解决: 8
您该题的状态:已完成
[提交][状态][讨论版]
题目描述
数字三角形,从三角形顶部往下走,只能往左下或右下走,求走到最下面时所经过的数字和最大为多少?(下图为n=6时的情况)
2 | ||||||||||
96 | 30 | |||||||||
83 | 52 | 60 | ||||||||
21 | 65 | 44 | 61 | |||||||
8 | 79 | 50 | 41 | 21 | ||||||
61 | 41 | 50 | 38 | 79 | 10 |
输入
第1行:整数n(1<=n<=1000)
第2-n+1行:每行若干整数,第i行有i-1个整数,空格分隔。
输出
一行:一个整数,表示所经过数字的最大和。
样例输入
6
2
96 30
83 52 60
21 65 44 61
8 79 50 41 21
61 41 50 38 79 10
样例输出
375
AC代码:
递归算法:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int n;
int a[1005][1005];
int dp[1005][1005];//dp[i][j]表示从点(i,j)出发能走过的最大和
int getdp(int i,int j)//计算dp[i][j]
{
if(dp[i][j]!=-1) return dp[i][j];//如果已经处理过就直接返回值,剪枝
return dp[i][j]=a[i][j]+(i==n?0:max(getdp(i+1,j),getdp(i+1,j+1))); //i=n时就到最后一层了,递归开始回溯
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
scanf("%d",&a[i][j]),dp[i][j]=-1;//赋初值-1的目的:getdp(i,j)的时候通过看dp[i][j]是否不等于-1可得知它是否被处理过,剪枝
printf("%d\n",getdp(1,1));//最终求从点(1,1)出发到最后一层经过的最大和
return 0;
}
递推算法(逆序枚举):
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int n;
int a[1005][1005];
int dp[1005][1005];//dp[i][j]表示从点(i,j)出发能走过的最大和
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
scanf("%d",&a[i][j]),dp[i][j]=0,dp[n][j]=a[n][j];//初始最大值都是0,最后一行最大值是自身
for(int i=n-1;i>=1;i--)//从倒数第二行第一个数开始赋值
for(int j=1;j<=i;j++)
dp[i][j]=a[i][j]+max(dp[i+1][j],dp[i+1][j+1]);
printf("%d\n",dp[1][1]);//最终求从点(1,1)出发到最后一层经过的最大和
return 0;
}