题意:

一个能向左移动1格或两格,向右能移动1格或两格,也能移动0格的人,在水平宽为W,高度为H的区域内,能接到的馅饼的分值最大为多少。馅饼给出了它掉落的初始时刻、水平位置、掉落速度、分值。

思路:

和数塔类似,把饼落到人高度的时间算出来(人占一格高),然后以时间为横坐标,水平位置为纵坐标,创建一个二维数组,先把馅饼落到人身上的时刻的位置赋上这个馅饼的分数,并且找到落到人身上最后的馅饼的时刻,往0时刻计算,dp[0][W/2]就是最后的答案。状态就是dp[i][j]=下一个时刻他能到达的5个位置里的最大值+dp[i][j]

代码:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
const int N=1500;
ll dp[N][N];//表示第i时刻j位置最大的分值是多少
int wzz[N][N];//记录方案
struct Pie{
    ll t,x,v,sco,en;
}p[1500];//存馅饼

void print(int x,int y,int maxn)
{
    if(x==maxn) return;
    if(dp[x+1][y+wzz[x][y]]!=0) cout<<wzz[x][y]<<endl;
    print(x+1,y+wzz[x][y],maxn);
}

int main(){
    int W,H;
    cin>>W>>H;
    int n=1;
    while(cin>>p[n].t>>p[n].x>>p[n].v>>p[n].sco)
    {
        if((H-1)%p[n].v || p[n].x>W || p[n].x<1) continue;//判断馅饼是否合法,看一下它的高度是否能被它的速度整除,如果不能,那么它落到的时刻就是个小数,在前一秒做出判断也不知道能不能接到。
        p[n].en=(H-1)/p[n].v+p[n].t;//(H-1),人占一格高
        n++;
    }
    ll maxn=0;
    n-=1;//n是馅饼数,之前多加了1,减掉1.
    //cout<<n<<endl;
    for(int i=1;i<=n;i++)
    {
        maxn=max(p[i].en,maxn);//寻找馅饼掉落到人身上的最晚时间
        dp[p[i].en][p[i].x]+=p[i].sco;//在馅饼掉落到人身上的时刻,在馅饼的水平位置上,这个时刻这个位置的最大分值就是接到了这个馅饼,如果从起始位置在馅饼下落时间内接不到也没关系,它从起点到不了这个位置,那么它从这个位置也到不了起点
    }
    
    /*for(int i=0;i<=maxn;i++)//可以输出一下刚开始的dp数组看一眼
    {
        for(int j=1;j<=W;j++)
        {
            printf("%4d",dp[i][j]);
        }
        cout<<endl;
    }*/
    
    for(int i=maxn-1;i>=0;i--)//maxn-1开始,maxn时刻不用做选择
    {
        for(int j=1;j<=W;j++)
        {
            int ans=0;
            int wz=0;
          //从后往前看所以左右得注意一下
            if(j>2 && ans<dp[i+1][j-2]) ans=dp[i+1][j-2],wz=-2;//顺序要从左到右(也没看到题目有说明。。。。),就是判断的顺序是左2步,左1步,0步,右1步,右2步
            if(j>1 && ans<dp[i+1][j-1]) ans=dp[i+1][j-1],wz=-1;
            if(ans<dp[i+1][j]) wz=0,ans=dp[i+1][j];
            if(j<W && ans<dp[i+1][j+1]) ans=dp[i+1][j+1],wz=1;
            if(j<W-1 && ans<dp[i+1][j+2]) ans=dp[i+1][j+2],wz=2;
            
            
            dp[i][j]+=ans;
            wzz[i][j]=wz;
        }
    }
    
    
    /*for(int i=0;i<=maxn;i++)//可以输出一下处理完的dp数组看一眼
    {
        for(int j=1;j<=W;j++)
        {
            printf("%4d",dp[i][j]);
        }
        cout<<endl;
    }*/
    
    /*for(int i=0;i<=maxn;i++)//对应的方案可以看一眼,wzz[i][j]就是记录它下一步要去哪.
    {
        for(int j=1;j<=W;j++)
        {
            printf("%4d",wzz[i][j]);
        }
        cout<<endl;
    }*/
    
    //cout<<maxn<<endl;
    cout<<dp[0][W/2+1]<<endl;
    
    print(0,W/2+1,maxn);//输出方案
    
    
    
    
    return 0;
}