bzoj千题计划156:bzoj1571: [Usaco2009 Open]滑雪课Ski

http://www.lydsy.com/JudgeOnline/problem.php?id=1571

 

DP不一定全部全状态转移

贪心的舍去一些不合法的反而更容易转移

在一定能力范围内,肯定滑雪所需时间越少越好

当课程的结束时间和能力值改变相同时,肯定课程越晚开始越好

预处理

late[i][j] 表示结束时间为i,能力值变成j的课程的最晚开始时间

mi[i] 表示在滑雪能力值<=i时,滑一次雪所需的最短时间

dp[i][j] 表示时间i,能力值为j时,最多的滑雪次数

f[i] 表示时间i最多的滑雪次数

喝可可:dp[i][j]=dp[i-1][j]

上课:dp[i][j]=f[late[i][j]]

滑雪:dp[i][j]=dp[i-mi[j]][j]+1

f[i]=max(dp[i][j])

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
 
using namespace std;
 
#define N 101
#define M 10001
 
int dp[M][N],f[M];
 
int late[M][N],mi[N];
 
void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}
 
int main()
{
    int t,s,n;
    read(t);
    read(s);
    read(n);
    int start,last,turn;
    for(int i=1;i<=s;++i)
    {
        read(start);
        read(last);
        read(turn);
        late[start+last][turn]=max(late[start+last][turn],start);
    }
    int need,tim;
    memset(mi,63,sizeof(mi));
    for(int i=1;i<=n;++i)
    {
        read(need);
        read(tim);
        mi[need]=min(mi[need],tim);
    }
    for(int i=1;i<=100;++i) mi[i]=min(mi[i],mi[i-1]);
    memset(dp,128,sizeof(dp));
    dp[0][1]=f[0]=0;
    for(int i=1;i<=t;++i)
        for(int j=1;j<=100;++j)
        {
            dp[i][j]=dp[i-1][j];
            if(late[i][j]) dp[i][j]=max(dp[i][j],f[late[i][j]]);
            if(i-mi[j]>=0) dp[i][j]=max(dp[i][j],dp[i-mi[j]][j]+1);
            f[i]=max(f[i],dp[i][j]);
        }
    cout<<f[t];
}

 

posted @ 2017-12-21 08:55  TRTTG  阅读(239)  评论(0编辑  收藏  举报