数塔dp的变形。
从“整个过程分为许多秒,每一秒都要做一个决策,当前位置可转移到最多左右1
个单位”这些特征可以看出,这是个类似数塔的dp过程。每一秒只能在一个位置获取馅饼(这一点题目没说清楚),所以把每秒看成数塔的每一层,每层都是11
个结点(代表每个位置),每个结点可访问下层的三个结点(不是边界的情况下)。还说“同一秒钟在同一点上可能掉下多个馅饼”,这就意味着数塔上结点的值可以大于1
。那么在输入同时建立这个数塔。
数塔长这样:(数塔的层数就是数据中最大的秒数,给的那个n
没什么用)
代码中加了一个虚拟的第0
层,只是为了直接输出答案(dp[0][5]
),不用再写max(max(dp[1][4],dp[1][5]),dp[1][6])
了。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
#include <queue>
using namespace std; // 数塔dp只用1个数组就行
int dp[100000][11]; // 每秒代表一层,每层都是11的结点
int N;
int maxT; // 层数
void init()
{
memset(dp, 0, sizeof dp); // 必须要初始化
maxT = -1;
}
int main()
{
int a, b;
for (; ~scanf("%d", &N);)
{
if (N == 0) break;
init();
for (; N--;)
{
scanf("%d%d", &a, &b);
dp[b][a]++;
maxT = max(maxT, b);
}
for (int i = maxT - 1; i >= 0; i--) // 多了一个第0层,代表初始状态(这一层肯定不会有馅饼)
{
for (int j = 0; j <= 10; j++)
{
if (j == 0) // 加条件判断边界,就不用琢磨怎么初始化边界了
dp[i][j] += max(dp[i + 1][j], dp[i + 1][j + 1]);
else if (j == 10)
dp[i][j] += max(dp[i + 1][j], dp[i + 1][j - 1]);
else
dp[i][j] += max(max(dp[i + 1][j], dp[i + 1][j + 1]), dp[i + 1][j - 1]);
}
}
printf("%d\n", dp[0][5]);
}
return 0;
}