【LSGDOJ 1850】滑雪课程

题目描述

贝西去科罗拉多州去滑雪,不过还她不太会玩,只是个能力为 1 的渣渣。贝西从 0 时刻进入滑雪场,一到 T 时刻就必须离开。滑雪场里有 N 条斜坡,第 i 条斜坡滑行一次需要 D i 分钟,要求游客的能力达到 C i 或以上时才能进入。贝西决心参加一些滑雪课程以提高自己的素质,这样可以在有限的时间内多滑几次坡。

滑雪场提供了 S 门课程。第 i 门课的开始时刻为 M i ,持续 L i 分钟,如果想参加课程,就不能迟到或早退。上完课之后,贝西的滑雪能力将变成 A i 。注意,不是能力增加 A i ,而是变成 A i ,所以乱上课的话反而会使能力下降。贝西可以随意安排她的时间:滑雪、上课,或美美地喝上一杯可可汁。请问她如何安排上课和滑雪的时间,滑坡的次数才能达到最大?

输入

• 第一行:三个整数 T,S 和 N,1 ≤ T ≤ 10 4 ,1 ≤ S ≤ 100,1 ≤ N ≤ 10 4

• 第二行到 S +1 行:第 i+1 行描述了第 i 门课程,分别为 M i ,L i 和 A i ,1 ≤ M i ,L i ≤ 10 4 ,1 ≤A i ≤ 100

• 第 S + 2 行到 S + N + 1 行:第 S + i + 1 行描述了第 i 条斜坡,分别为 C i 和 D i ,1 ≤ C i ≤100,1 ≤ D i ≤ 10 4

输出

• 单个整数,表示贝西可以滑完的最大次数

样例输入

10 1 2 3 2 5 4 1 1 3

样例输出

6

提示

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

题解:

F[i][j] 表示第i秒能力值为j时的最大滑的次数

然后背包,每次用合法状态(F[i][j]!=-1)去更新后面的状态

但暴力dp过不了 加一个贪心优化掉10000

Ft[j]表示能力值为<=j的最小滑坡时间,我们就不必枚举每一个滑坡去选最小的了.

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 using namespace std;
 7 const int N=10005,M=105;
 8 int gi(){
 9     int str=0;char ch=getchar();
10     while(ch>'9' || ch<'0')ch=getchar();
11     while(ch>='0' && ch<='9')str=str*10+ch-48,ch=getchar();
12     return str;
13 }
14 int F[N][M];
15 struct sor
16 {
17     int to,sta,l;
18 }e[M];
19 struct Chan
20 {
21     int l,lim;
22 }c[N];
23 bool comp(const sor &p,const sor &q){return p.sta<q.sta;}
24 int n,s,m,last[M];
25 int check(int x)
26 {
27     int l=1,r=s,mid;
28     while(l<=r){
29         mid=(l+r)>>1;
30         if(e[mid].sta==x)return mid;
31         if(e[mid].sta>x)r=mid-1;
32         else l=mid+1;
33     }
34     return -1;
35 }
36 bool cmp(const Chan &p,const Chan &q){return p.lim<q.lim;}
37 int pf(int x)
38 {
39     int ans,l=1,r=m,mid;
40     while(l<=r){
41         mid=(l+r)>>1;
42         if(c[mid].lim<=x)ans=mid,l=mid+1;
43         else r=mid-1;
44     }
45     return ans;
46 }
47 int ft[N];
48 int getmin(int x)
49 {
50     int minn=1999999999;
51     for(int i=1;i<=x;i++)
52     if(c[i].l<minn)minn=c[i].l;
53     return minn;
54 }
55 int main()
56 {
57     //freopen("pp.in","r",stdin);
58     n=gi();s=gi();m=gi();
59     int mh=0,minn=N;
60     for(int i=1;i<=s;i++)
61     {
62         e[i].sta=gi();e[i].l=gi();e[i].to=gi();
63         if(e[i].to>mh)mh=e[i].to;
64     }
65     sort(e+1,e+s+1,comp);
66     for(int i=1;i<=m;i++){c[i].lim=gi(),c[i].l=gi();if(c[i].lim<minn)minn=c[i].lim;}
67     sort(c+1,c+m+1,cmp);
68     for(int i=1;i<=mh;i++)last[i]=pf(i);
69     for(int i=1;i<=mh;i++)ft[i]=getmin(last[i]);
70     memset(F,-1,sizeof(F));
71     F[0][1]=0;
72     int tmp,maxn=0;
73     for(int i=0;i<n;i++)
74     {
75         tmp=check(i);
76         maxn=0;
77         for(int j=1;j<=mh;j++)
78         {
79             if(F[i][j]==-1)continue;
80             F[i+ft[j]][j]=F[i][j]+1;
81             if(F[i][j]>F[i+1][j])F[i+1][j]=F[i][j];
82             if(tmp!=-1 && i+e[tmp].l<=n && F[i][j]>maxn)maxn=F[i][j];
83         }
84         if(tmp!=-1 && i+e[tmp].l<=n)F[i+e[tmp].l][e[tmp].to]=maxn;
85     }
86     int ans=0;
87     for(int i=1;i<=mh;i++)if(F[n][i]>ans)ans=F[n][i];
88     cout<<ans;
89     return 0;
90 }
原文地址:https://www.cnblogs.com/Yuzao/p/6917388.html