【DP】钓鱼

Description

  在一条水平路边,有n(2<=n<=100)个钓鱼湖,从左到右编号为1、2、…、n。佳佳有H(1<=H<=20)个小时的空于时间,他希望利用这个时间钓到更多的鱼。他从1出发,向右走,有选择的在一些湖边停留一定的时间(是5分钟的倍数)钓鱼。最后在某一个湖边结束钓鱼。佳佳从第i个湖到第i+1个湖需要走5*Ti分钟路,还测出在第i个湖停留,第一个5分钟可以钓到Fi条鱼,以后每再钓5分钟,鱼量减少Di。为了简化问题,佳佳假定没有其他人钓鱼,也没有其他因素影响他钓到期望数量的鱼。请编程求出佳佳最多能钓鱼的数量。

Input

  第一行一个整数n,表示湖的个数;
  第二行一个整数H,表示佳佳的空闲时间; 
  第三行有n个整数,依次表示每个湖第一个5分钟能钓到鱼的数量;
  第四行有n个整数,依次表示以后的每5分钟钓鱼数量比前一个5分钟钓鱼数量减少的数量;
  第五行有n-1个整数,Ti表示由第i个湖到第i+1个湖需要花 5*Ti 分钟的路程;

Output

  只有一行,表示佳佳最多能钓鱼的数量。

Sample Input

314 5 61 2 11 2

Sample Output

35

Hint

  【样例说明】:
    在第1个湖钓15分钟,共钓得4+3+2=9条鱼; 
    在第2个湖钓10分钟,共钓得5+3=8条鱼; 
    在第3个湖钓20分钟,共钓得6+5+4+3=18条鱼; 
    从第1个湖到第2个湖,从第2个湖到第3个湖,共用时间15分钟。 
    共得35条鱼,并且这是最多的数量。
    

这题没有后效性,所以采用DP,主要思路为DP鱼塘的位置和此时的时间。本体难点为换鱼塘和时间的处理。(当然下面这种做法不是最好的,可以用一个数组来处理每一个鱼塘什么时候有多少鱼)

变量的用处和循环的理解详见代码注释。

#include<bits/stdc++.h>
using namespace std;
long long maxn=-0xfffffff/2,i,j,k,n,h,f[105][5005],d[105],dp[105][5005],t[105];
//f[i][j]表示第i塘第j*5min时的鱼 d[]表示变化鱼 t[]换鱼塘时间 dp[i][j]表前i个前j*5分最大鱼数 
int main()
{
	cin>>n>>h;
        h*=12;
	for(i=1;i<=n;i++)scanf("%lld",&f[i][1]);
	for(i=1;i<=n;i++)scanf("%lld",&d[i]);
	memset(dp,-1,sizeof(dp));
	dp[0][0]=0;
	for(i=1;i<=n;i++)
	{
	    long long cnt=1;
		while(f[i][cnt]>=d[i]&&cnt<=h)
		{
			cnt++;
			f[i][cnt]=f[i][cnt-1]-d[i];
		}	
	} 
	for(i=2;i<=n;i++)scanf("%lld",&t[i]);
	for(i=0;i<n;i++)//鱼塘 
	for(j=0;j<=h;j++)//时间 
	{
		long long sum=0;//如果不换后处理 
		for(k=0;k<=h&&dp[i][j]!=-1;k++)//换鱼塘时间 
		{
			if(j+t[i+1]+k>h) break;
			dp[i+1][j+t[i+1]+k]=max(dp[i][j]+sum,dp[i+1][j+t[i+1]+k]);
            if(f[i+1][k+1]>0) sum+=f[i+1][k+1];
		}
	}
	for(i=1;i<=n;i++)
	maxn=max(maxn,dp[i][h]);
	cout<<maxn;
}

猜你喜欢

转载自blog.csdn.net/disangan233/article/details/80927456