[USACO09OPEN]Ski Lessons

嘟嘟嘟

 

先考虑这两点:

1.如果我们有结束时间相同的课程,且达到的能力相同,那么我们一定选择开始时间最晚的。

2.如果有能力值相同的滑雪坡,我们一定选择时间最短的。

因此先预处理两个数组。cla[i][j]代表在 i 时刻结束,能力值达到 j 的课程中开始的最晚时间,ski[i]代表需要能力值至少为 i 的滑雪坡中最短的时间。

令dp[i][j] 表示 在 i 时刻,能力值为 j 时最多的滑雪次数,g[j]表示在当选前的时刻 i 时能力值为 j 时最多的滑雪次数,则 g[j] = max(dp[i][k]) (k:1~j)。

转移的时候分一下几种情况:

1.喝可可汁:dp[i][j] = dp[i - 1][j]。

2.如果有课刚好上完: if(cla[i - 1][j]) dp[i][j] = max(dp[i][j], g[cla[i - 1][j]]);

3.如果当前的时间可以滑一次能力值至少为 j 的滑雪坡:if(i - ski[j] >= 0) dp[i][j] = max(dp[i][j], dp[i - ski[j]][j] + 1);

4.最后更新g[i] = max(dp[i][j])。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a) memset(a, 0, sizeof(a))
15 typedef long long ll;
16 typedef double db;
17 const int INF = 0x3f3f3f3f;
18 const int eps = 1e-8;
19 const int maxn = 1e4 + 5;
20 const int maxm = 105;
21 inline ll read()
22 {
23     ll ans = 0;
24     char ch = getchar(), last = ' ';
25     while(!isdigit(ch)) {last = ch; ch = getchar();}
26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
27     if(last == '-') ans = -ans;
28     return ans;
29 }
30 inline void write(ll x)
31 {
32     if(x < 0) x = -x, putchar('-');
33     if(x >= 10) write(x / 10);
34     putchar(x % 10 + '0');
35 }
36 
37 int t, s, n, Max = 1;
38 int cla[maxn][maxm], ski[maxm];
39 int dp[maxn][maxm], g[maxn];
40 
41 int main()
42 {
43     t = read(); s = read(); n = read();
44     for(int i = 1; i <= s; ++i)
45     {
46         int m = read(), l = read(), a = read();
47         cla[m + l - 1][a] = max(m, cla[m + l - 1][a]);
48         Max = max(Max, a);
49     }
50     for(int i = 1; i <= Max; ++i) ski[i] = INF; 
51     for(int i = 1; i <= n; ++i)
52     {
53         int c = read(), d = read();
54         for(int j = c; j <= Max; ++j) ski[j] = min(ski[j], d);
55     }
56     memset(dp, 128, sizeof(dp));    //要初始化一个很小的值 
57     dp[0][1] = g[0] = 0;
58     for(int i = 1; i <= t; ++i)
59     {
60         for(int j = 1; j <= Max; ++j)
61         {
62             dp[i][j] = dp[i - 1][j];
63             if(cla[i - 1][j]) dp[i][j] = max(dp[i][j], g[cla[i - 1][j]]);
64             if(i - ski[j] >= 0) dp[i][j] = max(dp[i][j], dp[i - ski[j]][j] + 1);
65             g[i] = max(g[i], dp[i][j]);
66         }
67     }
68     write(g[t]); enter;
69     return 0;
70 }
View Code

 

posted @ 2018-08-30 11:44  mrclr  阅读(169)  评论(0编辑  收藏  举报