首页 > 代码库 > Usaco 滑雪比赛 Bobsledding, 2009 Dec(dp)

Usaco 滑雪比赛 Bobsledding, 2009 Dec(dp)

Description

滑雪比赛bobsled

贝西参加了一场高山急速滑雪比赛,滑道总长度为 L。出发时,她的初速度为 1,贝西可以加速 或减速,每过 1 米,她能将速度增加 1、减少 1 或保持不变。在滑雪的过程中,贝西会遇到 N 个转 弯点,编号为 i 的转弯点距离起点有 Ti 米。安全起见,贝西到达 i 号转弯点时的速度不能超过 Si。 穿过终点的速度是没有限制的。请问在整个比赛过程中,贝西能够达到的最大速度是多少?

Input Format

第一行:两个整数 L 和 N,2 ≤ L ≤ 10^9; 1 ≤ N ≤ 10^5

第二行到第 N + 1 行:第 i + 1 行有两个整数 T 和 S ,1 ≤ T < L; 1 ≤ S ≤ 10^9

Output Format

单个整数:表示贝西在比赛过程中能够达到的最大速度

Sample Input

14 3
7 3
11 1
13 8

Sample Output

5

Hint

第一次达到最高速度的位置在距离起点 4 米 处

Source

Bobsledding, 2009 Dec
一道需要预处理的dp
很明显 要以每个转弯点为状态 f[i]表示到第i个拐弯点的速度max;
由于可以任意加减或保持速度 那么易得到达i点速度小于f[i]的状态是一定能到达的;所以只要记录max
且我们不能只考虑是否能转移到当前状态;因为后面拐弯点的最小速度也可能
影响到当前状态;
一个例子
20 3
3 3
13 20
15 7
只考虑
当前与之前的状态的话 在第二个拐弯点速度能达到 13;
而正确答案是 11;因为若f[2]=13 那么就不能转移到f[3]的状态;
那么我们只要从后往前预处理 s[i]=min(s[i],s[i+1]+t[i+1]-t[i]);
那么就满足无后效性质了;
进行dp f[i]=min(f[i-1]+t[i]-t[i-1],s[i]);
然后打擂台 maxn=max(maxn,(f[i]+f[i-1]+t[i]-t[i-1])/2);
最后注意要先按t排序
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,j,k,l,m,maxx,i;
int f[100010];
struct st
{
	int s,t;
}mu[100010];
bool cmp( const  st x,  const st y)
{
	if(x.t<y.t)return true;
	return false;
}
int main()
{
//	freopen("xx.in","r",stdin);
	scanf("%d%d",&l,&n);
	for(i=1;i<=n;++i)
	scanf("%d%d",&mu[i].t,&mu[i].s);
	sort(mu+1,mu+1+n,cmp);
	f[0]=1;mu[n+1].s=1e9;mu[n+1].t=l;
	for(i=n;i>=1;--i)
		mu[i].s=min(mu[i].s,mu[i+1].s+mu[i+1].t-mu[i].t);
	for(i=1;i<=n+1;++i)
	{
		f[i]=min(mu[i].s,f[i-1]+mu[i].t-mu[i-1].t);
		 maxx=max((mu[i].t-mu[i-1].t+f[i]+f[i-1])/2,maxx);
	}
	printf("%d",maxx);
}

  

Usaco 滑雪比赛 Bobsledding, 2009 Dec(dp)