【BZOJ】1571: [Usaco2009 Open]滑雪课Ski
【算法】动态规划
【题解】yy出了O(1w log 1w)的算法。
将雪坡排序预处理出g[i]表示能力值为i的最短时长雪坡。
这样就可以定义work(t,c)表示时长t能力c的最多滑雪数量,work(t,c)=t/g[c]。
然后将课程按结束时间排序。
f[i]=f[j]+work(a[i].begin-a[j].end,g[a[j].c])。
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> using namespace std; const int maxn=10010,inf=0x3f3f3f3f; int f[maxn],T,n,m,g[maxn]; struct cyca{int begin,end,c;}a[maxn]; struct cycb{int c,d;}b[maxn]; int read() { char c;int s=0,t=1; while(!isdigit(c=getchar()))if(c=='-')t=-1; do{s=s*10+c-'0';}while(isdigit(c=getchar())); return s*t; } bool cmpb(cycb a,cycb b) {return a.c<b.c;} bool cmpa(cyca a,cyca b) {return a.end<b.end;} int main(){ T=read();n=read();m=read(); for(int i=1;i<=n;i++){ a[i].begin=read()+1; a[i].end=read();a[i].end+=a[i].begin-1; a[i].c=read(); } for(int i=1;i<=m;i++){ b[i].c=read(); b[i].d=read(); } sort(b+1,b+m+1,cmpb); int num=inf; for(int i=1;i<=m;i++){ num=min(num,b[i].d); g[b[i].c]=num; } g[0]=-1; for(int i=1;i<=100;i++)if(!g[i])g[i]=g[i-1]; sort(a+1,a+n+1,cmpa); a[0].c=1; n++;a[n].begin=a[n].end=T+1;//a[n].c=inf; for(int i=1;i<=n;i++){ f[i]=0; for(int j=0;j<=i-1;j++){ if(a[j].end>=a[i].begin)break; //if(a[j].c>=a[i].c)continue; f[i]=max(f[i],f[j]+(~g[a[j].c]?(a[i].begin-a[j].end-1)/g[a[j].c]:0)); } } printf("%d",f[n]); return 0; }