题目大意:初始能力为1,共时间T,每段时间有三种决策
1.什么都不干
2.上课,从Mi开始,持续时间为Li,能力变为Ai
3.滑雪,斜坡的能力要求为Ci,消耗时间为Di
求最多滑雪次数
题解:f[i][j]表示时间为i,能力为j的最多滑雪次数
三种决策,贪心地转移
每次滑雪肯定选能滑的里面时间最短的
同一时间结束的课到达相同能力值肯定选开始最晚的
1.f[i][j]=f[i−1][j]
2.f[i][j]=f[k][任意],k<i
3.minuse[i]表示能力值小于i的斜坡最短用时,f[i][j]=f[i−minuse[j]][j]+1
预处理l[i][j]表示时间i结束,能力值达到j的课程的最晚开始时间,g[i]=max(f[i][j]),这样就可以转移2了
我的收获:蜜汁优化,感觉不是很会这种贪心减少枚举量的trick
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
const int M=10005;
int T,S,n;
int f[M][105],g[M],L[M][105];
int minuse[105];
void work()
{
memset(f,0x80,sizeof(f));f[0][1]=0;
for(int i=1;i<=T;i++)
for(int j=1;j<=100;j++){
f[i][j]=f[i-1][j];
if(L[i-1][j]) f[i][j]=max(f[i][j],g[L[i-1][j]]);
if(i-minuse[j]>=0) f[i][j]=max(f[i][j],f[i-minuse[j]][j]+1);
g[i]=max(g[i],f[i][j]);
}
printf("%d\n",g[T]);
}
void init()
{
cin>>T>>S>>n;
int m,l,a,c,d;
for(int i=1;i<=S;i++){
scanf("%d%d%d",&m,&l,&a);
L[m+l-1][a]=max(L[m+l-1][a],m);
}
memset(minuse,0x3f,sizeof(minuse));
for(int i=1;i<=n;i++){
scanf("%d%d",&c,&d);
for(int j=c;j<=100;j++)
minuse[j]=min(minuse[j],d);
}
}
int main()
{
init();
work();
return 0;
}