[USACO09OPEN]滑雪课Ski Lessons
动态规划:
我们设计状态$f[i][j]$表示第$i$时刻,能力值为$j$能滑雪的最多次数
预处理出:
$a[i][j]$表示以$i$这个时刻结束,能力值为$j$时最晚的滑雪课开始时间
$les[i]$表示至少需要能力为$i$的最短滑雪时间
$g[i]$表示$i$时刻能滑雪的最多次数
状态转移:
$f[i][j]=f[i-1][j]$ //喝可可,什么都不做。。
$f[i][j]=max(f[i][j],g[a[i-1][j]])$ //上课,那么$f[i][j]$就是开始时间滑雪最多次数
$f[i][j]=max(f[i][j],f[i-les[j]][j]+1)$ //滑雪,那么现在的值就是$i-les[j]$时刻最大值$+1$
更新$g$数组
代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define N 10007 #define M 107 using namespace std; int t,s,n; int f[N][M],a[N][M],g[N],les[N]; int main() { scanf("%d%d%d",&t,&s,&n); for(int i=1;i<=s;++i) { int in1,in2,in3; scanf("%d%d%d",&in1,&in2,&in3); a[in1+in2-1][in3]=max(a[in1+in2-1][in3],in1); } memset(les,0x3f,sizeof(les)); for(int i=1;i<=n;++i) { int in1,in2; scanf("%d%d",&in1,&in2); for(int j=in1;j<=100;++j) les[j]=min(les[j],in2); } memset(f,0xcf,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(a[i-1][j]) f[i][j]=max(f[i][j],g[a[i-1][j]]); if(i-les[j]>=0) f[i][j]=max(f[i][j],f[i-les[j]][j]+1); g[i]=max(g[i],f[i][j]); } } printf("%d",g[t]); return 0; }