HDU1176 免费馅饼【数塔问题】

免费馅饼

题意: 人物最开始站在坐标为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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值