【NOI1998】免费馅饼,膜一膜XYX大爷

免费馅饼
SERKOI最新推出了一种叫做“免费馅饼”的游戏:游戏在一个舞台上进行。舞台的宽度为W格,天幕的高度为H格,游戏者占一格。开始时游戏者站在舞台的正中央,手里拿着一个托盘。下图为天幕的高度为4格时某一个时刻游戏者接馅饼的情景。
游戏开始后,从舞台天幕顶端的格子中不断出现馅饼并垂直下落。游戏者左右移动去接馅饼。游戏者每秒可以向左或向右移动一格或两格,也可以站在原地不动。
馅饼有很多种,游戏者事先根据自己的口味,对各种馅饼依次打了分。同时,在8-308电脑的遥控下,各种馅饼下落的速度也是不一样的,下落速度以格/秒为单位。
当馅饼在某一秒末恰好到达游戏者所在的格子中,游戏者就收集到了这块馅饼。
写一个程序,帮助我们的游戏者收集馅饼,使得所收集馅饼的分数之和最大。
输入
输入文件的第一行是用空格隔开的两个正整数,分别给出了舞台的宽度W(1到99之间的奇数)和高度H(1到100之间的整数)。
接下来依馅饼的初始下落时间顺序给出了所有馅饼的信息。每一行给出了一块馅饼的信息。由四个正整数组成,分别表示了馅饼的初始下落时刻(0到1000秒),水平位置、下落速度(1到100)以及分值。游戏开始时刻为0。从1开始自左向右依次对水平方向的每格编号。
输入文件中同一行相邻两项之间用一个或多个空格隔开。
输出
输出文件的第一行给出了一个正整数,表示你的程序所收集的最大分数之和。

样例输入
3 3
0 1 2 5
0 2 1 3
1 2 1 3
1 3 1 4
样例输出
12
说在前面:首先,这道题目的想法思路是XYX大爷想出来的,我只是觉得这个方法很神,所以就发上来了,所以本文作者实际上是XYX大爷。
————————————分分分割线——————————————
解题思路:简单来说就是建立一个时空坐标轴,通过馅饼的下落速度与起始时间来确定馅饼的坐标,以时间为Y轴,舞台宽度为X轴,每次向上走一格,转化成类似数字三角形的方法就可以了(我问XYX大爷你怎么想到转时间为坐标轴的,他说他从小就喜欢这么干(:з」∠)
代码:

#include<cstdio>
#include<iostream>
using namespace std;
int w,h;
struct os
{
    int time,pos,speed,value,t;
}a[10001];
int f[1000][100],zb[1000][100];
main()
{
    scanf("%d%d",&w,&h);
    int n=1;
    while (cin>>a[n].time>>a[n].pos>>a[n].speed>>a[n].value) 
    {
        a[n].t+=((h-2+a[n].speed)/a[n].speed)+a[n].time;//t指该馅饼下落下来(到最后一格)的时间
        //这一步比较难理解,核心意思就是将该时间取整,但是是加一位(2.....=3)我试过用我自己的方法取整,但只过了60%(╰_╯)#
        n++;
    }
    n--;
    int maxn=-999;
    for (int i=1;i<=n;i++)
    {
        f[a[i].pos][a[i].t]+=a[i].value;
        maxn=max(a[i].t,maxn);//找到最晚的馅饼的时间
    }
        for (int j=maxn-1;j>=0;j--)
    for (int i=1;i<=w;i++)
    {
        //进行dp寻找
        int ans=0;
        if (f[i-2][j+1]&&i-2>0)
        ans=max(ans,f[i-2][j+1]);
        if (f[i-1][j+1]&&i>1)
        ans=max(ans,f[i-1][j+1]);
        if (f[i][j+1])
        ans=max(ans,f[i][j+1]);
        if (f[i+2][j+1]&&i+2<=w)
        ans=max(ans,f[i+2][j+1]);
        if (f[i+1][j+1]&&i+1<=w)
        ans=max(ans,f[i+1][j+1]);
        f[i][j]+=ans;
    }

    printf("%d",f[w/2+1][0]);//由于人以中间为起点,所以输出(w/2+1,0)
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值