[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;
}

  

posted @ 2019-01-02 22:08  模拟退火  阅读(198)  评论(0编辑  收藏  举报