BSOJ1915 天堂的馈赠 基础递推类dp

10 篇文章 0 订阅
1 篇文章 0 订阅
1915 -- 【模拟试题】天堂的馈赠
Description
【题目背景】:
  小杉找到了做棉花糖的最优方案,想去摘云朵,可是摔死了……
  他来到了天堂。
  天堂当然是很大的,也是很缭乱的。
  小杉看到一块路标,写着“天堂的馈赠”。
【问题描述】:
    考虑到小杉刚死没多久,为了安抚他受创的心灵和思恋的感情,
  天堂派出一个天使给小杉送礼,但IQ不够高的小杉可不能够拿到好礼物。馈赠在天堂门口进行。天使站在云端,往下扔礼物。
  天堂之门的宽度为W格(按1..W编号),高度为0格,云端的高度为H格,小杉只能站在格子里。
  开始时(第0秒),小杉站在天堂之门的第P格。
  馈赠开始后,天使会在某些时刻从云端的某格扔礼物下来,礼物下落的速度(格/秒)是不一样的。
  小杉左右移动去接礼物(每秒可以移动1格或不移动)。
  礼物之间的价值当然是不一样的,小杉事先知道了每个礼物的价值。
  当礼物在某一秒末恰好到达小杉所在的格子中,小杉就接到了这个礼物。
  小杉想知道,他最多可以拿到价值为多少的礼物。
  而且,由于礼物下落的速度有些可以很……,小杉还想知道是不是有些礼物他怎么样也拿不到。
Input
  第一行有四个数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
Output
  输出两行。
  第一行仅有一个整数,表示小杉最多能拿到价值多少的礼物。
  第二行也仅有一个整数,表示小杉不可能拿到的礼物总价值多少。
Sample Input
1 1 1 1
1 1 1 1
Sample Output
1
0
Hint
  注意:当礼物在某一秒末 恰好 到达小杉所在的格子中,小杉才能接到这个礼物。

这道题目显然是一个dp,而且方程也很好想。
f[i][j]表示在i时刻和j位置所取到的最大值,那么我们可以得到方程为f[i][j]=max(f[i-1][j],f[i-1][j-1],f[i-1][j+1])+w[i][j];
其中w[i][j]表示i时刻j位置可以接到的价值。
那么我们只要预处理出w[i][j]就可以了。
但是有一些细节是需要注意的,比如说:
  • 当礼物在某一秒末 恰好 到达小杉所在的格子中,小杉才能接到这个礼物。 注意恰好。不在某一秒末的我们肯定是拿不到的
  • 还有拿不到的就是在一开始我们直接前往也无法拿到的。
  • 另外需要注意的是,某个礼物的价值可能是负的,那么f数组一定要赋-inf,否则要出事

代码还是比较简单的:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#define inf 0x3fffffff
using namespace std;
int w,p,h,n,t,r,v,s,ans2=0,ans=0,T,f[3005][3005],g[3005][3005];
int main(){
	cin>>w>>p>>h>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>t>>r>>v>>s;
		if(h%v==0)t+=h/v;
		else
		{
			ans2+=s;
			continue;
		}
		T=max(T,t);
		g[t][r]=s;
		if(abs(p-r)>t)
		  ans2+=s;
	}
	for(int i=0;i<=T;i++)
	  for(int j=0;j<=w+1;j++)
	    f[i][j]=-inf;
	f[0][p]=0;
	for(int i=1;i<=T;i++)
	  for(int j=1;j<=w;j++)
	    {
	    	if(f[i-1][j]!=-inf)f[i][j]=f[i-1][j]+g[i][j];
	    	if(f[i-1][j-1]!=-inf)f[i][j]=max(f[i][j],f[i-1][j-1]+g[i][j]);
	    	if(f[i-1][j+1]!=-inf)f[i][j]=max(f[i][j],f[i-1][j+1]+g[i][j]);
	    	ans=max(ans,f[i][j]);
		}
	cout<<ans<<"\n"<<ans2;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值