题解 | #免费馅饼#

免费馅饼

https://ac.nowcoder.com/acm/problem/16850

思路:dp

开一个dp[i][j]数组,其中i代表位置,j代表时间

然后在馅饼恰好收集到的时候dp[pos][t]+=val(pos代表馅饼位置,t代表下落到的时间,val代表馅饼价值)

之后我们按时间从后往前枚举位置与操作即可

为什么不从前往后枚举?

因为你一开始的位置你是知道是dp[w/2+1][0]的

如果往后枚举那么就不知道最大的价值在哪个位置,就不好弄方案

往前枚举就让dp[w/2+1][0]这时候拥有的价值最大

再另外开个la[i][j]数组保存方案即可

具体见代码注释

AC代码:

#define long long int
using namespace std;
int dp[150][1350];//i表示位置,j表示时间
int la[150][1350];
int dx[]= {-2,-1,0,1,2};
signed main()
{
    int w,h;
    cin>>w>>h;
    int a,b,c,d;
    int mmax=0;
    while(cin>>a>>b>>c>>d)
    {
        if((h-1)%c)continue;
        int t=a+(h-1)/c;
        mmax=max(t,mmax);
        dp[b][t]+=d;
    }
    for(int i=mmax-1; i>=0; i--)
    {
        for(int j=1; j<=w; j++)
        {
            int ma=0,p=0;
            for(int k=0; k<5; k++)//模拟移动操作,找下一秒能到达的最大价值点
            {
                int pos=j+dx[k];
                if(pos>w||pos<1)continue;
                if(dp[pos][i+1]>ma)
                {
                    ma=dp[pos][i+1];
                    p=dx[k];
                }
            }
            la[j][i]=p;//记录方案
            dp[j][i]+=ma;
        }
    }
    int pos=w/2+1,t=0;
    cout<<dp[pos][0]<<endl;
    while(dp[pos][t])
    {
        int x=la[pos][t];
        pos+=x,t++;//之后位置跟时间都变了
        if(dp[pos][t])cout<<x<<endl;
    }
    return 0;
}

全部评论
为什么dx中的-2和-1换位置就错了
1
送花
回复
分享
发布于 2022-02-28 19:40

相关推荐

点赞 评论 收藏
转发
2 收藏 评论
分享
牛客网
牛客企业服务