【DP“基础”】天堂的馈赠

题目描述

小杉找到了做棉花糖的最优方案,想去摘云朵,可是摔死了…… 他来到了天堂。 天堂当然是很大的,也是很缭乱的。 小杉看到一块路标,写着“天堂的馈赠”。 考虑到小杉刚死没多久,为了安抚他受创的心灵和思恋的感情, 天堂派出一个天使给小杉送礼,但IQ不够高的小杉可不能够拿到好礼物。 馈赠在天堂门口进行。天使站在云端,往下扔礼物。 天堂之门的宽度为W格(按1..W编号),高度为0格,云端的高度为H格,小杉只能站在格子里。 开始时(第0秒),小杉站在天堂之门的第P格。 馈赠开始后,天使会在某些时刻从云端的某格扔礼物下来,礼物下落的速度(格/秒)是不一样的。 小杉左右移动去接礼物(每秒可以移动1格或不移动)。 礼物之间的价值当然是不一样的,小杉事先知道了每个礼物的价值。 当礼物在某一秒末恰好到达小杉所在的格子中,小杉就接到了这个礼物。 小杉想知道,他最多可以拿到价值为多少的礼物。 而且,由于礼物下落的速度有些可以很……,小杉还想知道是不是有些礼物他怎么样也拿不到。

输入

每组测试数据的 第一行有四个数W,P,H,N(1<=P<=W<=500),(1<=H<=500),(0<=N<=3000) 接下来N行,每行四个数t,r,v,s(0<=t<=1500),(1<=r<=W),(1<=v<=H),(|s|<=1e5) 表示天使在t时刻,云端的第r格,以v格/秒的速度扔下价值s的礼物 输入均为正整数 10%的数据W<=100,H<=100,N<=200

输出

对每组测试数据输出两行。 第一行仅有一个整数,表示小杉最多能拿到价值多少的礼物。 第二行也仅有一个整数,表示小杉不可能拿到的礼物总价值多少。

样例输入

 (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

1 1 1 1
1 1 1 1

样例输出

1
0

虽说是一道DP基础题,但是坑还是不少.....OI制的话就死了..

设dp[i][j]表示在时间i到了j处所得到的礼物最大值(因为礼物是强制接受的,这样DP好处理)
则 dp[i][j]=max{dp[i-1][j],dp[i-1][j-1],dp[i-1][j+1]}+W[i][j] (W[i][j]表示i时刻j格处的礼物价值)

注意:(1)因为题目只是说礼物价值的绝对值<=100000,但可能为负数,故数组初值要设为-INF
      (2)题目说“当礼物在某一秒末到达小衫所在的格子时,小衫就接到了这个礼物”,也就是说礼物到达格子的时间必须为整数,不然就无法接到。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;

#define MAXN 3000
#define MAXM 500
#define MAXT 2000
#define INF 0x3f3f3f3f
typedef long long int LL;

int G[MAXT+10][MAXM+10];
int dp[MAXT+10][MAXM+10];
int W,P,H,N,T;

int main()
{
    //freopen("data3.in","r",stdin);

    scanf("%d%d%d%d",&W,&P,&H,&N);
    int i,j;
    int t,r,v,s;
    int ans1=0,ans2=0;

    T=0;
    for(i=1;i<=N;++i)
    {
        scanf("%d%d%d%d",&t,&r,&v,&s);
        if(!(H%v))t+=H/v;
        else
        {
            ans2+=s;
            continue;
        }

        G[t][r]+=s;
        T=max(T,t);

        ans2+=(abs(P-r)>t)*s;
    }

    for(i=0;i<=T;++i)
        for(j=0;j<=W+1;++j)dp[i][j]=-INF;
    dp[0][P]=0;

    for(i=1;i<=T;++i)
        for(j=1;j<=W;++j)
        {
            if(dp[i-1][j]!=-INF)dp[i][j]=dp[i-1][j]+G[i][j];
            if(dp[i-1][j-1]!=-INF)dp[i][j]=max(dp[i][j],dp[i-1][j-1]+G[i][j]);
            if(dp[i-1][j+1]!=-INF)dp[i][j]=max(dp[i][j],dp[i-1][j+1]+G[i][j]);
        }

    for(i=1;i<=W;++i)
        ans1=max(ans1,dp[T][i]);

    printf("%d\n%d\n",ans1,ans2);
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值