免费馅饼 |
---|
题意: 人物最开始站在坐标为5的位置,每秒钟最多横向移动一个单位,并且只能接住一个单位距离内的的馅饼。天上会在某个时刻在某个位置掉落馅饼,问人物最多能够接住几个馅饼。
题解: 这是一个典型的数塔问题,如果你非要较真,从5出发,去计算到最后时刻,所有移动的可能性,以及所有的接住馅饼数,那真有你的 。当然不能这么做咯,当一个问题正向思考过于复杂的时候,我们就应该试着逆向思考了。
- 最大时刻。既然要逆向DP,就要清楚馅饼掉落的最大时刻,从这一时刻,一直逆推回时间0。
- 定义状态
dp[i][t]
:表示t时刻在位置i所能接住的最多馅饼数。 - 状态转移
dp[i][t] = max{dp[i - 1][t + 1], dp[i][t + 1], dp[i + 1][t + 1]} + xb[i][t]
。应该很好理解,因为某个时刻,人物只能接住在他一个单位距离内的馅饼。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
#define dbg(x...) \
do { \
cout << #x << " -> "; \
err(x); \
} while (0)
void err() { cout << endl;}
template <class T, class... Ts>
void err(const T& arg, const Ts&... args) {
cout << arg << ' ';
err(args...);
}
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
const int N = 1e5 + 10;
int n;
int xb[20][N];
int dp[20][N];
void run() {
int maxt = 0;
memset(xb, 0, sizeof xb);
memset(dp, 0, sizeof dp);
for (int i = 0; i < n; i++) {
int x = read(), t = read();
xb[x + 1][t]++;
maxt = max(maxt, t);
}
for (int i = 0; i < 13; i++)
dp[i][maxt] = xb[i][maxt];
for (int j = maxt - 1; j >= 0; j--) {
for (int i = 1; i <= 11; i++) {
dp[i][j] = max(dp[i - 1][j + 1], max(dp[i][j + 1], dp[i + 1][j + 1])) + xb[i][j];
}
}
printf("%d\n", dp[6][0]);
}
int main() {
while(~scanf("%d", &n) && n)
run();
return 0;
}