hdu 3905 sleeping

这是一道很明显的动态规划

动态规划方程如下: j表示前j分钟 i表示休息了i分钟 l 表示需要连续学习l分钟

以前 F[j][i] = f[j - 1][i-1] ;//如果当前不选择,那么当前的最大价值就是前j-1分钟选择i-1分钟休息的最大价值

                  = f[j-l][i]+sum(j-l,j)//如果当前选择的,那么的最大价值就等于前j-l分钟,休息i分钟的最大价值最大价值,加上学习了(j-l,j)这l分钟的价值

                    // 但是,他可能不止连续学习l分钟,可能会大学l分钟啊。。所以选择的方程因该改为学习了k分钟,而k>=l

                 =f[j-k][i]+sum(j-k,j) k=l,l+1,。j - i 中的最大价值

很明显这是一个o(n^3)的方程,会超时的 只有o(n^2)才不会超时啊~

          这该怎么把方程将为二维呢。。我们另外设置一个数组sel[j][i]来表示当前第j分钟一定会被选择 a[j]表示当前的分钟的得分

          那么对于sel[j][i]=sel[j-k][i]+sum(j-k,j) k=l,l+1,。j - i 中的最大价值

                        那么sel[j+1][i]=sel[j-k+1][i]+sum(j-k+1,j)k=l,l+1,...j+1-i 两者之间似乎有点相似之处。。

                              当k=m时,sel[j][i] = sel[j - l][i] + sum(j-l,j) 

                                               sel[j+1][i] = sel[j+1-l][i]+sum(j+1-l,j+1) //不能被前j分钟选择i分钟休息包括

                              当k=m+1时sel[j][i]=sel[j-l-1][i] + sum(j-l-1,j);

                                              sel[j+1][i]=sel[j+1-l-1] +sum(j+1-l-1,j+1)

                                                            =sel[j-l]+sum(j-l,j+1) 

                                                            =sel[j-l] + sum(j-l,j)+a[j];

                              当k = m+2时 sel[j][i] = sel[j-l-2][i]+sum(j-l-2,j)

                                                  sel[j+1] = sel[j+1-l-2] +sum(j+1-l-2,j+1)

                                                             = sel[j-l-1]+sum(j-l-1,j+1)

                                                             = sel[j-l-1][i] + sum(j-l-1,j) +a[j]

                         观察画横线的地方是不是一样的。而所有的画横线都在sel[j][i]中就计算过一次了,

                        规律很明显了

                             sel[j+1][i] = max(sel[j+1-l][i]+sum(j+1-l,j+1),sel[j][i] + a[j]);

                             即当前点分钟被选择,有两种情况,一种是就选择l分钟

                                                                                       另外一种选择大于l分钟,   之中的最大

                             

                 

/*************************************************************************
	> File Name: hdu3905.cpp
	> Author: zwy
	> Mail: zwy_qz@hotmail.com 
	> Created Time: 2012年11月25日 星期日 12时35分26秒
 ************************************************************************/

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
int f[1009][1009];
int sel[1009][1009];
int a[1009];
int total[1009];
int n,m;
int _max(int a,int b)
{
	if(a > b) return a;
	return b;
}
void print(int f[][1009])
{
	int i,j;
	putchar('\n');

	for(j = 0 ; j <= m ;j++)
	{
		for(i = 0 ; i < n ; i++)
			printf("%5d ",f[i][j]);
		putchar('\n');
	}
}
int main()

{
	int l;
	int i,j;
	int temp;
	//freopen("in.txt","r",stdin);
	while(scanf("%d%d%d",&n,&m,&l)!=EOF)
	{
		memset(f,0,sizeof(f));
		memset(total,0,sizeof(total));
		memset(sel,0,sizeof(sel));
		for(i = 0 ; i < n ; i ++)
		{
			scanf("%d",&a[i]);
			if(i == 0 )
				total[i] = a[i];
			else
				total[i] = total[i-1] + a[i]; //前i分钟的和
			f[i][0] = total[i];
			sel[i][0]=total[i];
	//		printf("%d ",total[i]);
		}
		
	//	printf("\n");
		for(i = 1 ; i <= m ; i++)
		{
			for(j = l + i - 1 ; j < n ; j++)
			{
				int a1 = sel[j-1][i] + a[j]; //选择了大于l分钟进行学习
				int a2 = f[j-1][i-1];
				int a3 = f[j - l][i] + total[j] - total[j-l];//选择了了l分钟
				sel[j][i] =_max(a1,a3);//当前选择的最大值等于两者之中的最大
				f[j][i] = _max(a2,sel[j][i]);
	//			printf("%d ",j);
			}
	//		printf("\n");
		}
	//	print(f);
	//	print(sel);
		int mymax = 0;
		for(j = 0 ; j < n ; j++)
			mymax=_max(mymax,f[j][m]);
		printf("%d\n",mymax);
	}
	fclose(stdin);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值