我不想写背景

69 篇文章 0 订阅

我不想写背景


题目描述

某巨魔去滑雪(没滑雪板),但他的技术并不精湛,在滑雪场里,每天会提供 S 门滑雪课。
i 节课始于时间 Mi ,上课的时长为 Li (只有在 Mi 时刻才能选择去上第 i 节课,其他时间不能选择上第 i 节课)。
上完第 i 节课后,巨魔的滑雪能力会变成 Ai. (注意:这个能力是绝对的,不是能力的增长值)。
巨魔买了一张地图,地图上显示了 N 个可供滑雪的斜坡,从第 i 个斜坡的顶端滑至底部所需的时长 Di ,以及每个斜坡所需要的滑雪能力 Ci ,以保证滑雪的安全性。
巨魔的能力必须大于等于这个等级,以使得他能够安全滑下。
巨魔可以用他的时间来滑雪,上课,或者在旁边菊花丛中练习箭法,但是他必须在 T 时刻离开滑雪场。
这意味着他必须在 T 时刻之前(或者 T 时刻)完成最后一次滑雪(或者上课)。
求巨魔在时间内最多可以完成多少次滑雪。
这一天开始的时候,他的滑雪能力为 1


输入格式

第一行 3 个数字,T S N
接下来 S 行,每行 3 个数字 Mi Li Ai
接下来 N 行,每行 2 个数字 Ci Di


输出格式

一个整数,表示巨魔滑雪的最大次数。


样例输入

10 1 2
3 2 5
4 1
1 3


样例输出

6


样例解释

0时刻,选择在第1个斜坡上滑雪,时间花费3。
3时刻,选择上第1节课。滑雪技术提高到5,时间花费2。
5时刻,选择在第2个斜坡上滑雪,时间花费1。
6时刻,选择在第2个斜坡上滑雪,时间花费1。
7时刻,选择在第2个斜坡上滑雪,时间花费1。
8时刻,选择在第2个斜坡上滑雪,时间花费1。
9时刻,选择在第2个斜坡上滑雪,时间花费1。
10时刻,收队了。
总滑雪次数:6


数据范围

50% 的数据: 1N,T1000
100% 的数据: 1N,T10000 1S,Ai,Ci100 1Mi,Li,Di10000


Solution

f[i][j] 表示当前等级为 i ,时刻为 j 的最多滑雪次数。
转移方程就很容易推了。


Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>

using namespace std;

int oo=(2147483647);

struct answer{
    int i,j,k;
    answer(int a,int b,int c){
        i=a;
        j=b;
        k=c;
    }
    bool operator > (const answer num)const{
        if(i!=num.i)return i>num.i;
        if(j!=num.j)return j>num.j;
        if(k!=num.k)return k>num.k;
    }
};

struct object{
    int l,t,v;
    object(){
        l=t=v=oo;
    }
};

struct snow{
    int c,d;
    snow(){
        c=d=oo;
    }
};

inline int Max(int a,int b){
    return a>b?a:b;
}

inline int in(){
    char ch;
    int x=0,flag=1;
    ch=getchar();
    while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
    if(ch=='-'){flag=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x;
}

int t,s,n,rn,ans;
int maxn;
object o[10010];
snow w[10010];
priority_queue<answer,vector<answer>,greater<answer> >S;

bool cmp(object a,object b){
    return a.l<b.l;
}

bool cmp2(snow a,snow b){
    return a.c<b.c; 
}

void prework(){
    scanf("%d%d%d",&t,&s,&n);                                       
    rn=n;                                                   
    for(int i=1;i<=s;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if(x+y<=t){
            o[i].l=x;
            o[i].t=y;
            o[i].v=z;
            maxn=Max(maxn,o[i].v);
        }
        else
            o[i].l=oo;
    }
    for(int i=1;i<=n;i++){
        scanf("%d%d",&w[i].c,&w[i].d);
        if(w[i].c>maxn){w[i].c=oo;rn--;}
    }

    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)if(w[j].c!=oo&&w[i].c!=oo){
            if(w[i].c<=w[j].c&&w[i].d<=w[j].d){w[j].c=oo;rn--;}
            if(w[i].c>=w[j].c&&w[i].d>=w[j].d){w[i].c=oo;rn--;}
        }

    for(int i=0;i<=t;i++)
        S.push(answer(i,1,0));
    sort(o+1,o+s+1,cmp);
    sort(w+1,w+n+1,cmp2);
}

void mainwork(){
    int now=1;

    while(!S.empty()){
        answer nos=S.top();
        S.pop();
        while(!S.empty()&&nos.i==(S.top()).i&&nos.j==(S.top()).j){
            nos.k=(S.top()).k;
            S.pop();
        }
        while(o[now].l==nos.i){
            if(o[now].v>nos.j)
                S.push(answer(nos.i+o[now].t,o[now].v,nos.k));
            now++;
        }
        for(int k=1;k<=rn;k++){
            if(w[k].c>nos.j)break;
            if(nos.i+w[k].d<=t)
                S.push(answer(nos.i+w[k].d,nos.j,nos.k+1));
        }
        if(ans<nos.k)ans=nos.k;
    }
}

void endwork(){
    printf("%d",ans);
}

int main(){

    freopen("wtf.in","r",stdin);
    freopen("wtf.out","w",stdout);

    prework();                                  
    mainwork();
    endwork();

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值