您的位置:首页 > 其它

LightOJ 1004 Monkey Banana Problem

2017-11-08 16:12 274 查看
LightOJ 1004

题意:

题目给了一张地图,地图上的数字表示猴子走到这点后能够取得的香蕉数目,猴子只能从自己当前位置向下一行的相邻位置转移,求得到最多的香蕉的数量



这道题跟数字三角形是一个意思的,只是这道题的走的图形不是一个三角形而是菱形,菱形相当于一个正的三角形和一个倒着的三角形拼接而成的。

我们来看菱形的上部分,用dp[i][j]表示在i,j位置得到的最大的香蕉数量.

如果从上往下推:不难发现对于每个边缘的位置,只能从它的上一行的一个位置推下来,比如dp[2][1]位置,只能由dp[1][1]走下来,而dp[3][3]只能由dp[2][2]走下来,而除了dp[i][1]和dp[i][i]这样的边界位置,其余的位置都是由上一行的相邻两个位置推出的,这就涉及到了边界处理

转移方程为:

if(j == 1) dp[i][j] = dp[i - 1][j] + map[i][j];

if (j == i) dp[i][j] = dp[i - 1][j - 1] + map[i][j];

else dp[i][j] = max(dp[i - 1][j - 1], dp[i - 1][j]) + map[i][j];

如果倒着推:不难发现,对于每一个元素,都是由下一行的两个相邻位置转移过来的, 所以不存在边界处理,我想这就是为啥在做数字三角形的时候,大佬们选择倒推的原因吧。。。

转移方程为:

dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]) + map[i][j];

很不幸,这道题不管是正着推还是倒推,都会涉及边界处理,因为这有一个倒着的三角形~ 这个倒着的三角形处理实际上跟上面讲的一样,不过如果正三角形是正推那倒三角形就倒推,如果正三角形倒推那倒三角形就正推啦~

下面附上AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int T, N;
const int MAXN = 1e2 + 10;
int map[MAXN * 2][MAXN];
int dp[MAXN * 2][MAXN];
void input() {  //输入数据
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= i; j++) {
cin >> map[i][j];
}
}
for (int i = N + 1; i <= 2 * N - 1; i++) {
for (int j = 1; j <= 2 * N - i; j++) {
cin >> map[i][j];
}
}
}
int main() {
scanf("%d", &T);
int Case = 0;
while (T--) {
cin >> N;
input();
memset(dp, 0, sizeof dp);
//初始赋值
dp[2 * N - 1][1] = map[2 * N - 1][1];
//我是选择的从最后往前推,倒三角形包含边界处理
for (int i = 2 * N - 2; i >= N; i--) {
for (int j = 1; j <= 2 * N - i; j++) {
if (j == 1) dp[i][j] = dp[i + 1][j] + map[i][j];
else if (j == 2 * N - i) dp[i][j] = dp[i + 1][j - 1] + map[i][j];
else dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - 1]) + map[i][j];
}
}
for (int i = N - 1; i >= 1; i--) {
for (int j = 1; j <= i; j++) {
dp[i][j] = max(dp[i + 1][j], dp[i + 1][j + 1]) + map[i][j];
}
}
cout << "Case " << ++Case << ": ";
cout << dp[1][1] << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp lightoj