USACO 滑雪课程

#include<cstdio>
#include<iostream>
using namespace std;

int T,S,N,maxd;
int len[120],lv[120],next[120],first[10010];//注意这个first要开到和极限时间一样
int mintime[120];//表示在级别i的时候 能够滑的最短时间赛道 
int dp[11010][110]; 


int main()
{
    freopen("ski.in","r",stdin);
    freopen("ski.out","w",stdout);
    //=========================
    for(int i=0;i<120;i++) //预处理mintime  设成最大 这样才能求最小 
    {
        mintime[i]=1<<30;
    }
    scanf("%d%d%d",&T,&S,&N);
    //读入课程的信息  为了能实现记录同一时间出现多门课程的情况
    //我们使用类似边信息表的思想 建立数组 len[i] 表示第i门课程持续时间
    //next[i] 表示第i门课程的兄弟课程编号 就是开始时间一样的
    //lv[i] 表示第i门课程上完达到的level 
    //first[i] 注意 i表示第i秒开始的课程编号 
    for(int i=1,a,b,c;i<=S;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        len[i]=b;
        lv[i]=c;
        next[i]=first[a];
        first[a]=i; 
        maxd=max(maxd,c);
    }
    
    
    //接下来读入滑雪赛道信息 我们知道要滑的尽量多 时间就要短
    //所以要预处理下最短时间赛道
    
    for(int i=1,c,d;i<=N;i++)
    {
        scanf("%d%d",&c,&d);
        for(int j=c;j<=100;j++)
        {
            mintime[j]=min(mintime[j],d);
        }
    } 
        
    //到这一步应该检查mintime数组到底对不对
    //接下来进行递推操作 在上次说的状态转移方程基础上 我们要以时间i为单位
    //枚举在i时间下的所有级别j的可能性 从左往右 在二维表上一列一列的更新
    //简单说就是左边时间的状态想办法让右边的时间状态变得更大 
    //我们在dp二维表上进行运算
    
    
    for(int i=0;i<=T+1;i++)
    {
        for(int j=0;j<=100;j++)
        {
            dp[i][j]=-9999;
        }
    } 
    
    dp[0][1]=0;
    for(int i=0;i<T;i++)
    {
        for(int j=0;j<=100;j++)
        {
            if(dp[i][j]==-9999) continue;
            
            dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
            dp[i+mintime[j]][j]=max(dp[i+mintime[j]][j],dp[i][j]+1);
            
            int p=first[i];
            while(p!=0)
            {
                dp[i+len[p]][lv[p]]=max(dp[i+len[p]][lv[p]],dp[i][j]);
                p=next[p];
            }
        }
    }
    int ans=-9999;
    for(int i=0;i<=maxd;i++)
    {
        ans=max(ans,dp[T][i]);
        //cout<<dp[T][i]<<" "; 这里可以输出最后一行的答案看看正确性 
    }
    printf("%d",ans);
    
    //=========================
    fclose(stdin);
    fclose(stdout);
    return 0;
}

农夫约翰想带着他的奶牛Bessie去佛罗里达滑雪,可是,Bessie的滑雪技术真是太差了。

她了解到滑雪学校全天提供滑雪课程,共有S(0 <= S <=100)个滑雪课程可供选择,课程i从时间M_i(1 <= M_i <= 10,000)开始,持续时间为L_i(1 <= L_i <= 10,000),学完该课程滑雪水平将提升至A_i(1 <= A_i <= 100),注意:滑雪水平的提升是绝对的,而不是累加的。

此外Bessie还买了一张滑雪练习场的地图,从图中可以看到练习场每个斜坡的详细情况:从坡上滑下来所需的时间D_i(1 <= D_i <= 10,000),以及滑这个坡所需要的水平等级C_i(1 <= C_i <= 100),为安全起见,只有滑雪水平高于该坡所要求的等级,才可以从这个坡滑下。

Bessie可以把她所有的时间都花在滑雪、上课上,当然她也可以去喝杯热可可,但前提是她必须得在滑雪学校待至时间T(1 <= T <= 10,000),这也意味着她的最后一趟滑坡行动不得超过这个时限。

请确定在这个时间段内,Bessie最多可以滑多少趟斜坡,假定她当天的起始水平为1。

输入格式:
第1行,三个空格隔开的整数:T,S,N;
第2~S+1行,第i+1行有三个空格隔开的整数M_i,L_i,A_i,描述了一个课程的情况;
第S+2~S+N+1行,第S+i+1行为两个空格隔开的整数,C_i,D_i,描述了一个斜坡的情况。

输出格式:
一行,一个整数,即在时限内Bessie能完成的滑坡的最大次数。

样例:
ski.in
10 1 2
3 2 5
4 1
1 3

ski.out
6

输出数据说明
先滑一次第2个斜坡,然后在时间3去上课,上课至时间5,然后在时间结束之前可以再滑五次第1个斜坡,所以共6次滑坡。

 

提交地址 http://cogs.pro/cogs/problem/problem.php?pid=754

 

posted on 2016-12-13 23:41  清老师  阅读(152)  评论(0编辑  收藏  举报