【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 }