DP(数塔问题) - 免费馅饼 - HDU - 1176

DP(数塔问题) - 免费馅饼 - HDU - 1176

题意:

有 11 个 位 置 0 , 1 , 2 , . . . , 10 , 初 始 时 站 在 5 号 位 置 , 每 秒 钟 可 以 向 任 意 方 向 移 动 一 个 长 度 单 位 , 有11个位置0,1,2,...,10,初始时站在5号位置,每秒钟可以向任意方向移动一个长度单位, 110,1,2,...,105
在这里插入图片描述

给 定 n 个 行 数 据 , 每 行 包 括 两 个 整 数 x 和 t , 表 示 在 t 时 刻 x 位 置 , 有 一 个 馅 饼 , 给定n个行数据,每行包括两个整数x和t,表示在t时刻x位置,有一个馅饼, nxttx

要 计 算 从 5 出 发 , 最 多 能 够 获 得 多 少 个 馅 饼 。 要计算从5出发,最多能够获得多少个馅饼。 5

输入:

多 组 测 试 数 据 , 多组测试数据,

每 组 包 括 一 个 正 整 数 n 每组包括一个正整数n n

接 着 n 行 , 每 行 两 个 正 整 数 x 和 t 接着n行,每行两个正整数x和t nxt

输出:

一 个 正 整 数 , 表 示 获 得 馅 饼 的 最 大 数 量 。 一个正整数,表示获得馅饼的最大数量。

Sample Input

6
5 1
4 1
6 1
7 2
7 2
8 3
0

Sample Output

4

数据范围:

0 < n , t < 100000 0<n,t<100000 0<n,t<100000


分析:

如 下 图 : 如下图:
在这里插入图片描述
当 t > = 6 时 , 是 事 实 上 可 以 从 5 走 到 0 到 10 的 任 意 位 置 。 当t>=6时,是事实上可以从5走到0到10的任意位置。 t>=65010

如 果 我 们 反 过 来 考 虑 , 这 就 是 一 个 数 塔 问 题 。 如果我们反过来考虑,这就是一个数塔问题。

我 们 记 w [ i ] [ j ] : 表 示 i 时 刻 在 j 位 置 处 的 馅 饼 数 量 。 f [ i ] [ j ] : 表 示 t 时 刻 在 j 位 置 处 最 多 能 够 获 得 的 馅 饼 数 量 。 我们记w[i][j]:表示i时刻在j位置处的馅饼数量。f[i][j]:表示t时刻在j位置处最多能够获得的馅饼数量。 w[i][j]:ijf[i][j]:tj

如 果 我 们 自 底 向 上 考 虑 , 每 个 点 的 最 大 值 都 取 决 于 下 方 连 续 的 2 或 3 个 点 的 最 大 值 。 如果我们自底向上考虑,每个点的最大值都取决于下方连续的2或3个点的最大值。 23

即 : f [ i ] [ j ] = m a x ( f [ i + 1 ] [ j − 1 ] , f [ i + 1 ] [ j ] , f [ i + 1 ] [ j + 1 ] ) + w [ i ] [ j ] 即:f[i][j]=max(f[i+1][j-1],f[i+1][j],f[i+1][j+1])+w[i][j] f[i][j]=max(f[i+1][j1],f[i+1][j],f[i+1][j+1])+w[i][j]

那 么 终 点 就 是 0 时 刻 在 起 点 位 置 5 的 值 。 那么终点就是0时刻在起点位置5的值。 05

考 虑 到 边 界 问 题 , 为 了 简 化 代 码 , 把 所 有 位 置 向 右 平 移 1 个 长 度 单 位 。 考虑到边界问题,为了简化代码,把所有位置向右平移1个长度单位。 1

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>

using namespace std;

const int N=100010;

int f[N][15];
int n;
int w[N][15];
int t, x;

int main()
{
    while(~scanf("%d",&n),n)
    {
        memset(w,0,sizeof w);
        memset(f,0,sizeof f);
        int T=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&x,&t);
            w[t][x+1]++;
            T=max(T,t);
        }
        for(int i=1;i<=11;i++) f[T][i]=w[T][i];
        
        for(int i=T-1;i>=0;i--)
            for(int j=1;j<=11;j++)
            {
                f[i][j]=max(f[i+1][j],max(f[i+1][j-1],f[i+1][j+1]))+w[i][j];
            }
        
        printf("%d\n",f[0][6]);
    }
    
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值