下图是个数字三角,请编写一个程序计算从顶部至底部某处一条路径,使得该路径所经过的数字总和最大。
7
3 8
8 1 0
2 7 4 4
1. 每一步可沿左斜线向下或右斜线向下走;
2. 1<=三角形行数<=100
3. 三角形中的数字为整数 0,1,……,99。
4. 如果有多种情况结果都最大,任意输出一种即可。
输入:
第一行一个整数N,代表三角形的行数。
接下来N行,描述了一个数字三角。
输出:
第一行一个整数,代表路径所经过底数字总和。
第二行N个数,代表所经过的数字。
样例:
输入:
4
7
3 8
8 1 0
2 7 4 4
输出:
25
7 3 8 7
题意:给定一个数字三角,求cong顶至下路径上所有数字之和最大那个最大数,并且输出路径上经过的数。
思路:dp思想,由于要输出过程,必须采用二维的DP,并且还要开另外一个数组记录每次走过的路径。
#include<bits/stdc++.h>
#include<cstring>
using namespace std;
int n;
int a[105][105],mark[105][105],s[105][105]; //mark用来标记,s用来记录路径
int dp(int a[105][105],int i,int j)
{
if(i==n-1) return a[i][j]; //从0开始,即到了n-1则到底部了,返回
if(mark[i][j]) return a[i][j];
int left=dp(a,i+1,j); //对于每一个数字,下一行的左右两种走法
int right=dp(a,i+1,j+1);
int maxn;
if(left>right)
{
maxn=left;
}
else {maxn=right,s[i][j]=1; } //s记录为右
return maxn+a[i][j];
}
void put(int i,int j)
{
//输出以a[i][j]为顶部的路径
if (i == n) return;
cout << a[i][j] << " ";
put(i + 1, j + s[i][j]);
}
int main()
{
int i,te;
scanf("%d",&n);
memset(a,0,sizeof(a)); //初始化
memset(s,0,sizeof(s));
memset(mark,0,sizeof(mark));
for(int i=0;i<n;i++)
for(int j=0;j<=i;j++)
cin>>a[i][j];
printf("%d\n",dp(a,0,0));
put(0,0);
}
#include<cstring>
using namespace std;
int n;
int a[105][105],mark[105][105],s[105][105]; //mark用来标记,s用来记录路径
int dp(int a[105][105],int i,int j)
{
if(i==n-1) return a[i][j]; //从0开始,即到了n-1则到底部了,返回
if(mark[i][j]) return a[i][j];
int left=dp(a,i+1,j); //对于每一个数字,下一行的左右两种走法
int right=dp(a,i+1,j+1);
int maxn;
if(left>right)
{
maxn=left;
}
else {maxn=right,s[i][j]=1; } //s记录为右
return maxn+a[i][j];
}
void put(int i,int j)
{
//输出以a[i][j]为顶部的路径
if (i == n) return;
cout << a[i][j] << " ";
put(i + 1, j + s[i][j]);
}
int main()
{
int i,te;
scanf("%d",&n);
memset(a,0,sizeof(a)); //初始化
memset(s,0,sizeof(s));
memset(mark,0,sizeof(mark));
for(int i=0;i<n;i++)
for(int j=0;j<=i;j++)
cin>>a[i][j];
printf("%d\n",dp(a,0,0));
put(0,0);
}