【DP例题】滑雪


题目

描述

Farmer John wants to take Bessie skiing in Colorado. Sadly, Bessie is not really a very good skier.

Bessie has learned that the ski resort is offering S (0 <= S <= 100) ski classes throughout the day. Lesson i starts at time M_i (1 <= M_i <= 10,000) and lasts for time L_i (1 <= L_i <= 10,000). After lesson i, Bessie’s ski ability becomes A_i (1 <= A_i <= 100). Note: this ability is an absolute, not an incremental change.

Bessie has purchased a map which shows all N (1 <= N <= 10,000) ski slopes along with the time D_i (1 <= D_i <= 10,000) required to ski down slope i and the skill level C_i (1 <= C_i <= 100) required to get down the slope safely. Bessie’s skill level must be greater than or equal to the skill level of the slope in order for her to ski down it.

Bessie can devote her time to skiing, taking lessons, or sipping hot cocoa but must leave the ski resort by time T (1 <= T <= 10,000), and that means she must complete the descent of her last slope without exceeding that time limit.

Find the maximum number of runs Bessie can complete within the time limit. She starts the day at skill level 1.

Extra feedback will be provided on the first 50 submissions.

Farmer John 想要带着 Bessie 一起在科罗拉多州一起滑雪。很不幸,Bessie滑雪技术并不精湛。 Bessie了解到,在滑雪场里,每天会提供S(0<=S<=100)门滑雪课。第i节课始于M_i(1<=M_i<=10000),上的时间为L_i(1<=L_i<=10000)。

上完第i节课后,Bessie的滑雪能力会变成A_i(1<=A_i<=100). 注意:这个能力是绝对的,不是能力的增长值。

Bessie买了一张地图,地图上显示了N(1 <= N <= 10,000)个可供滑雪的斜坡,从第i个斜坡的顶端滑至底部所需的时长D_i(1<=D_i<=10000),以及每个斜坡所需要的滑雪能力C_i(1<=C_i<=100),以保证滑雪的安全性。Bessie的能力必须大于等于这个等级,以使得她能够安全滑下。

Bessie可以用她的时间来滑雪,上课,或者美美地喝上一杯可可汁,但是她必须在T(1<=T<=10000)时刻离开滑雪场。这意味着她必须在T时刻之前完成最后一次滑雪。 求Bessie在实现内最多可以完成多少次滑雪。这一天开始的时候,她的滑雪能力为1.

输入格式

  • Line 1: Three space-separated integers: T, S, and N
  • Lines 2…S+1: Line i+1 describes ski lesson i with three
    space-separated integers: M_i, L_i, and A_i
  • Lines S+2…S+N+1: Line S+i+1 describes ski slope i with two
    space-separated integers: C_i and D_i.
  • 第一行三个整数T,S,N
  • 接下来S行每行三个整数,M_i, L_i,A_i
  • 接下来N行,每行两个整数C_i,D_i

输出格式

  • A single integer on a line by itself, the maximum number of runs that Bessie may ski within the time limit.
  • 一个整数,Bessie在T时间内最多可以完成多少次滑雪。

输入/输出例子

输入

10 1 2
3 2 5
4 1
1 3

输出

6

提示


解题思路

分析

考虑到题目让我们在T时间内求最大滑雪次数,我们用DP来解决这题。

初始化

我们令dp[i][j]表示前i个时刻上前j门课时最大滑雪次数,a[i]表示能力值为i时最短多久滑一次雪,f[i].b,e,o分别表示第i节课的起,止时间和上完后的能力值,输入后以结束时间排序。
所以很容易有:

	struct fy
	{
		int b,e,o;
	}f[10001];
	bool cmp(fy x,fy y)
	{
		return x.e<y.e;
	}
	
	scanf("%d%d%d",&t,&n,&m);
    for(int i=1;i<=n;i++)
    	scanf("%d%d%d",&f[i].b,&x,&f[i].o),f[i].e=f[i].b+x-1;
	sort(f+1,f+n+1,cmp);
	fill(a,a+10001,1919810);
	for(int i=1;i<=m;i++)
		scanf("%d%d",&x,&y),a[x]=min(a[x],y);
	for(int i=1;i<=10000;i++)
		a[i]=min(a[i],a[i-1]);

同时,对于dp[i][0]来说,因为没上任何一节课,所以能力值为1,所起它的初始化为:

	for(int i=0;i<t;i++) 
		dp[i][0]=(i+1)/a[1];

动态转移方程

对于第j门课程:
1.若第j门课不上,则

dp[i][j]=dp[i][j-1];

2.若第j门课上,则f[i][j]=f[第j门课开始时间][上了第i节课还能上的最晚的课]+(i-第i门课结束时间)/上完课后滑雪的最优方案耗时:

	int ga(int u)//二分枚举上了第i节课还能上的最晚的课
	{
		int l=0,r=u-1;
		while(l+1<r)
		{
			int mid=(l+r)>>1;
			if(f[mid].e<f[u].b)
				l=mid;
			else
				r=mid;
		}
		return l;
	}
	if(i>f[j].e)//当前时间必须能上完第i节课
		dp[i][j]=max(dp[i][j],dp[f[j].b-1][ga(j)]+(i-f[j].e)/a[f[j].o]);

结尾

对dp[T-1][0~S]取max值:

	for(int j=0;j<=n;j++)
		ans=max(ans,dp[t-1][j]);

code

#include<bits/stdc++.h>
using namespace std;
int a[10001];
int dp[10001][101],x,y,ans,t,n,m;
struct fy
{
	int b,e,o;
}f[10001];
bool cmp(fy x,fy y)
{
	return x.e<y.e;
}
int ga(int u)
{
	int l=0,r=u-1;
	while(l+1<r)
	{
		int mid=(l+r)>>1;
		if(f[mid].e<f[u].b)
			l=mid;
		else
			r=mid;
	}
	return l;
}
int main()
{
    scanf("%d%d%d",&t,&n,&m);
    for(int i=1;i<=n;i++)
    	scanf("%d%d%d",&f[i].b,&x,&f[i].o),f[i].e=f[i].b+x-1;
	sort(f+1,f+n+1,cmp);
	fill(a,a+10001,1919810);
	for(int i=1;i<=m;i++)
		scanf("%d%d",&x,&y),a[x]=min(a[x],y);
	for(int i=1;i<=10000;i++)
		a[i]=min(a[i],a[i-1]);
	for(int i=0;i<t;i++) 
		dp[i][0]=(i+1)/a[1];
	for(int i=0;i<t;i++)
		for(int j=1;j<=n;j++)
		{
			dp[i][j]=dp[i][j-1];
			if(i>f[j].e)
				dp[i][j]=max(dp[i][j],dp[f[j].b-1][ga(j)]+(i-f[j].e)/a[f[j].o]);
		}
	for(int j=0;j<=n;j++)
		ans=max(ans,dp[t-1][j]);
	printf("%d",ans);
}

更多方法

P2948滑雪的更多方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值