【USACO】2009 Open Ski Lessons 滑雪课程

15 篇文章 0 订阅

Ski Lessons 滑雪课程


  • Description

约翰请贝西去科罗拉多去滑雪。不过贝西不太会玩,她只是个滑雪能力为1的渣渣。所以她决心参加一些滑雪课程。滑雪场提供S门课程,第i门课开始的时间是Mi,持续时间为Li ,上完课之后,贝西的滑雪能力将变成Ai。注意,能力不是增加Ai,而是变成Ai。
滑雪场有N条斜坡,第i条斜坡滑行一次需要Di 分钟,要求游客的滑雪能力达到Ci或以上时才能进入。
贝西可以随意安排她的时间:滑雪、上课,或美美地喝上一杯可可汁,但她在滑雪场只能呆到第T分钟。请问她如何安排时间,滑行次数才能尽量多?

  • Input Format

第一行:三个用空格分开的整数:T,S和N,1 ≤ T ≤ 10^4,1 ≤ S ≤ 100,1 ≤ N ≤ 10^5
第二行到S + 1行:第i + 1行描述了第i门课程,分别为Mi,Li 和Ai,彼此用空格隔开,1 ≤ Mi , Li ≤ 10^4,1 ≤ Ai ≤ 100
第S + 2行到S + N + 1行:第S + i + 1行描述了第i条斜坡,分别为Ci和Di ,彼此用空格隔开,1 ≤ Ci ≤ 100,1 ≤ Di ≤ 10^4

  • Output Format

第一行:单个整数,表示在时限内贝西可以滑完的最大次数

  • Sample Input

10 1 2
3 2 5
4 1
1 3

  • Sample Output

6

  • Hint

先滑 1 次 2 号斜坡,然后去上课,再去 1号连滑 5 次,一共 6 次


  • 分析

F[i][j]表示到了第i分钟,能力为j时最多能滑几次。
然后我们先把课程按结束时间排序。接着转移的时候,对于当前时刻,我们让他选择是从滑学,上课,还是休息转移过来。
我们还要预处理一下能力为i去滑哪个场。(肯定滑的越快越优)


一年前的代码,巨丑无比

#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
#include <ctime>
#include <cmath>
int i,j,k,t,s,n,ans,a[111],c,d,f[10011][111];
struct info{
    int m,l,a,en;
}e[102];
inline bool cmp(const info &a,const info &b){
    return a.en<b.en;
}
int main(){
    freopen("1016.in","r",stdin);
    freopen("1016.out","w",stdout);
    scanf("%d %d %d",&t,&s,&n);
    for (i=1;i<=s;i++){
        scanf("%d %d %d",&e[i].m,&e[i].l,&e[i].a);
        e[i].en=e[i].m+e[i].l;
    }
    std::sort(e+1,e+s+1,cmp);
    for (i=1;i<=100;i++) a[i]=1<<30;
    for (i=1;i<=n;i++){
        scanf("%d %d",&c,&d);
        a[c]=d<a[c]?d:a[c];
    }
    for (i=2;i<=100;i++){
        if (a[i-1]<a[i] && a[i-1]!=0) a[i]=a[i-1];      
    }
    for (i=0;i<=t;i++){
        for (j=0;j<=100;j++){
            f[i][j]=-99999999;
        }
    }
    f[0][1]=0;
    for (i=1;i<=t;i++){
        k=1;
        for (j=1;j<=100;j++){
            f[i][j]=std::max(f[i][j],f[i-1][j]);
            ans=std::max(ans,f[i][j]);
            if (i==e[k].en && k<=s){
                f[i][e[k].a]=std::max(f[e[k].m][j],f[i][e[k].a]);
                ans=std::max(ans,f[i][e[k].a]);
                k++;
            }
            if (i-a[j]>=0) f[i][j]=std::max(f[i][j],f[i-a[j]][j]+1),
            ans=std::max(ans,f[i][j]);
        }
    }
    printf("%d",ans);
    fclose(stdin); fclose(stdout);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值