Naptime

题目描述

rainbow给了freda N秒的自由活动时间,不过由于刚刚游览城堡有些累了,freda只想花B秒的时间来卖萌,剩下的时间她要在rainbow的城堡里睡个好觉好好休息一下。

rainbow给这N秒每秒定义了一个值Ui,如果第i秒钟freda在卖萌,那么她可以获得Ui点卖萌指数lala~

freda开始卖萌后可以随时停止,休息一会儿之后再开始。不过每次freda开始卖萌时,都需要1秒来准备= =,这一秒是不能获得卖萌指数的。当然,freda卖萌和准备的总时间不能超过B。

更特殊的是,这N秒钟时间是环形的。也就是freda可以从任意时间开始她的自由活动并持续N秒。

为了使自己表现得比水叮当更萌,现在freda想知道,她最多能获得多少卖萌指数呢?

输入格式

第一行包含两个整数N和B。

第2~N+1行每行一个整数,其中第i+1行的整数表示Ui。

输出格式

输出一个整数,表示freda可以获得的最大卖萌指数。

样例

数据范围

环形与后效性的处理这个就是要把环形断开,转化成线性,可以避免环形不必要的dfs枚举。这个题就是可以找n与1的地方断开,转化成两个问题,一个是1是不可能在休息的,二就是1一定是在休息的,这样就可以覆盖了整个问题。设f[i][j][1]表示前i个小时休息了j个小时,并且第i个小时正在休息, f[i][j][0]表示前i个小时休息了j个小时,并且第i个小时不在休息,然后列出DP方程

f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1]);

f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j-1][1]);

这是第一个问题的DP方程,初始化f[1][0][0]=0,f[1][1][1]=0;

接下来说一下第二个问题的DP方程,我们可以发现,两个问题的本质其实是一样的,只不过不同的只是初始化的时候不一样而已,第一个是0,而第二个初始化为a[i],再用上一个问题的DP方程解一遍找个最大值就好了。

代码

#include<bits/stdc++.h>
using namespace std;
int f[4000][4000][3],a[5000],maxx=-1000000000;
int main()
{
	freopen("naptime..in","r",stdin);
	freopen("naptime..out","w",stdout);
	int n,b;
	cin>>n>>b;
	memset(f,-10,sizeof(f));
	for(int i=1;i<=n;i++)
	cin>>a[i];
	f[1][1][1]=0;
	for(int i=1;i<=n;i++)
	f[i][0][0]=0;
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=b;j++)
		{
			f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1]);
			f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j-1][1]+a[i]);
		}
	}
	maxx=max(f[n][b][0],f[n][b][1]);
	memset(f,-10,sizeof(f));
	f[1][1][1]=a[1];
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=b;j++)
		{
			f[i][j][0]=max(f[i-1][j][0],f[i-1][j][1]);
			f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j-1][1]+a[i]);
		}
	}
	maxx=max(maxx,f[n][b][1]);
	cout<<maxx;
}

留下评论

通过 WordPress.com 设计一个这样的站点
从这里开始