数字三角形
题目描述
观察下面的数字金字塔。
写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以走到左下方的点也可以到达右下方的点。
7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大值。
思路一
由题意可以知道,每一个阶段的最大值由左上方或者右上方的最大值推导而来。
便可以得到状态转移方程:
DP[i][j] = max(DP[i-1][j],DP[i-1][j-1])+Triangle[i][j]
最后遍历底层最大值,求底层路径的最大值为最终答案。
#include <iostream>
#include <cstdio>
using namespace std;
int DP[1001][1001] = {0};
int Triangle[1001][1001] = {0};
int main(void)
{
int R;
scanf("%d",&R);
for(int i = 1;i <= R;i++)
{
for(int j = 1;j <= i;j++)
{
scanf("%d",&Triangle[i][j]);
}
}
int ans = 0;
for(int i = 1;i <= R;i++)
{
for(int j = 1;j <= i;j++)
{
DP[i][j] = max(DP[i-1][j],DP[i-1][j-1])+Triangle[i][j];
ans = max(ans,DP[i][j]);
}
}
cout << ans << endl;
return 0;
}
思路二
倒着推,从下往上推。最终答案就是DP[1][1].
状态转移方程:
DP[i][j] = Triangle[i][j] (i == R)
DP[i][j] = max(DP[i+1][j],DP[i+1][j+1])+Triangle[i][j];
#include <iostream>
using namespace std;
int DP[1001][1001];
int Triangle[1001][1001];
int main(void)
{
int R;
cin >> R;
for(int i = 1;i <= R;i++)
{
for(int j = 1;j <= i;j++)
{
cin >> Triangle[i][j];
}
}
for(int i = R;i > 0;i--)
{
for(int j = R;j >= 1;j--)
{
if(i == R)
{
DP[i][j] = Triangle[i][j];
}
else
{
DP[i][j] = max(DP[i+1][j],DP[i+1][j+1])+Triangle[i][j];
}
}
}
cout << DP[1][1];
return 0;
}
Likecloud-吃、吃、吃
题目背景
问世间,青春期为何物?
答曰:“甲亢,甲亢,再甲亢;挨饿,挨饿,再挨饿!”
题目描述
正处在某一特定时期之中的李大水牛由于消化系统比较发达,最近一直处在饥饿的状态中。某日上课,正当他饿得头昏眼花之时,眼前突然闪现出了一个n*m(n and m<=200)的矩型的巨型大餐桌,而自己正处在这个大餐桌的一侧的中点下边。餐桌被划分为了n*m个小方格,每一个方格中都有一个圆形的巨型大餐盘,上面盛满了令李大水牛朝思暮想的食物。李大水牛已将餐桌上所有的食物按其所能提供的能量打了分(有些是负的,因为吃了要拉肚子),他决定从自己所处的位置吃到餐桌的另一侧,但他吃东西有一个习惯——只吃自己前方或左前方或右前方的盘中的食物。
由于李大水牛已饿得不想动脑了,而他又想获得最大的能量,因此,他将这个问题交给了你。
每组数据的出发点都是最后一行的中间位置的下方!
这道题是比较坑的,因为没有说明李大水牛的朝向。
根据数据得到状态转移方程:
DP[i][j] = max(DP[i-1][j],DP[i-1][j+1],DP[i-1][j-1]) + Food[i][j];
//由上一个阶段的最大值加上现在的食物的能量值推导而来.
按照升序顺序遍历。
#include <iostream>
using namespace std;
int Map[201][201];
int DP[201][201] = {0};
int main(void)
{
int m,n;
cin >> m >> n;
for(int i = 1;i <= m;i++)
{
for(int j = 1;j <= n;j++)
{
cin >> Map[i][j];
}
}
int y = n/2 + 1;
for(int i = 1;i <= m;i++)
{
for(int j = 1;j <= n;j++)
{
//状态转移方程
//由上一个阶段的最大值加上当前位置F(x,y)的值
DP[i][j] = max(max(DP[i-1][j],DP[i-1][j+1]),DP[i-1][j-1]) + Map[i][j];
}
}
int ans = -25;
//语文阅读理解问题
ans = max(ans,DP[m][y+1]);
ans = max(ans,DP[m][y]);
ans = max(ans,DP[m][y-1]);
cout << ans << endl;
return 0;
}
最后提一句,通过得出的状态转移方程,可以推知状态转移方程计算的遍历顺序。
比如说这个状态转移方程中的 i - 1就可以知道需要先退出i小的最大值再来推现阶段的最大值。