【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;
}            
View Code

 

posted @ 2017-08-31 19:33  ONION_CYC  阅读(252)  评论(0编辑  收藏  举报