题目描述
小杉找到了做棉花糖的最优方案,想去摘云朵,可是摔死了…… 他来到了天堂。 天堂当然是很大的,也是很缭乱的。 小杉看到一块路标,写着“天堂的馈赠”。 考虑到小杉刚死没多久,为了安抚他受创的心灵和思恋的感情, 天堂派出一个天使给小杉送礼,但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);
}