数字三角形
题目描述
上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
输入描述
输入的第一行包含一个整数 N(1≤N≤100),表示三角形的行数。
下面的 N 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数。
输出描述
输出一个整数,表示答案。
用例输入 1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
用例输出 1
27
思路
从上往下模拟,当前这一层 坐标(x,y), 能走到下一层的 (x + 1,y - 1) 和(x + 1,y + 1),关于题目要求只需要记录往左和往右的步数,到达最后一层在判断即可
方法一 :dfs思想会超时
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 110;
int n;
int maxnum;
int note[maxn] = { 0 }, left1 = 0, right1 = 0, pos = 1;
int a[maxn][maxn];
void dfs(int x, int left, int right) {
if (x == n) { // 递归边界
if (abs(left - right) > 1) return;
note[x] = a[x][1 + right]; //
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += note[i];
}
if (sum > maxnum) maxnum = sum; // 刷新最大值
return;
}
note[x] = a[x][1 + right]; // 记录第x层的数字
dfs(x + 1, left + 1, right);
dfs(x + 1, left, right + 1);
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
cin >> a[i][j];
}
}
dfs(1,0,0); //
cout << maxnum << endl;
getchar();
getchar();
return 0;
}
方法二: 动态规划
思路:dp [i] [j] 代表前 i 层,第 j个位置所能到达的最大值,如果选择(i , j)
这个位置,说明就是上一层能到达这个位置的最大值,那么就是(i - 1,j),(i -
1,j - 1) ,但是题目还有要求往左和往右的步数差不超过一,其实这个就是走
到最后一层的中间,奇数就是中间的数,偶数就是中间两个数的最大值
动态转移方程: dp [i] [j] = max(dp [i - 1] [j] , dp [i - 1] [j - 1])
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
int a[105][105];
int n;
int dp[105][105];
int main(){
cin >> n ;
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= i ; j++){
cin >> a[i][j];
}
}
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= i ; j++){
dp[i][j] = max(dp[i - 1][j] ,dp[i - 1][j - 1])+ a[i][j];
}
}
if(n % 2 == 0) cout << max(dp[n][n / 2],dp[n][n / 2 +1]) << endl;
else cout << dp[n][n / 2 + 1];
return 0;
}