题目链接:点击打开链接
题目描述
话说发源于小朋友精心设计的游戏被电脑组的童鞋们藐杀之后非常不爽,为了表示安慰和鼓励,VIP999决定请他吃一次“年年大丰收”,为了表示诚意,他还决定亲自去钓鱼,但是,因为还要准备2013NOIP,z老师只给了他H(1<=H<=16)个小时的空余时间,假设有N(2<=n<=25)个鱼塘都在一条水平路边,从左边到右编号为1、2、3、。。。、n)。VIP是个很讲究效率的孩子,他希望用这些时间钓到尽量多的鱼。他从湖1出发,向右走,有选择的在一些湖边停留一定的时间钓鱼,最后在某一个湖边结束钓鱼。他测出从第I个湖到I+1个湖需要走5*ti分钟的路,还测出在第I个湖边停留,第一个5分钟可以钓到鱼fi,以后再每钓5分钟鱼,鱼量减少di。为了简化问题,他假定没有其他人钓鱼,也不会有其他因素影响他钓到期望数量的鱼。请编程求出能钓最多鱼的数量。
输入格式:第一行:湖的数量n。
第二行:时间h(小时)。
第三行:n个数,f1,f2,…fn。
第四行:n个数,d1,d2,….dn。
第五行:n-1个数,t1,t2,….tn-1
输出格式:
一个数,所能钓鱼的最大数量。
输入:
2
1
10 1
2 5
2
输出:
31
思路:
利用大根堆优化,加贪心计算。
忽略行走与间的时间(最后计算),贪心寻找钓鱼最多的鱼塘,
最后比较,得到最多。
code:
#include<iostream>
using namespace std;
struct Num
{
int fish;//每五分种能钓多少鱼
int num;//每五分种减少多少鱼
} a[101];
int f[101];//每五分种能钓多少鱼
int l[101];//每五分种减少多少鱼
int t[101];//相邻鱼塘走需要多少时间
int n,T,size;
void put(Num x)//大根堆
{
int now,next;
a[++size]=x;
now=size;
while(now>1)
{
next=now>>1;
if(a[now].fish<=a[next].fish)
return ;
swap(a[now],a[next]);
now=next;
}
return ;
}
void get()//维护,实时更新最有钓鱼方案
{
int now=1;
int next;
while(now*2<=size)//一定是 <=
{
next=now*2;
if(next<size&&a[next].fish<a[next+1].fish)
++next;
if(a[now].fish>=a[next].fish)
return ;
swap(a[now],a[next]);
now=next;
}
}
int main()
{
cin>>n;
cin>>T;
T=T*12;//转换时间单位,并把每五分钟等效换成每一分钟
for(int i=1; i<=n; ++i)
cin>>f[i];
for(int i=1; i<=n; ++i)
cin>>l[i];
for(int i=1; i<n; ++i)
cin>>t[i];
int t1=0,maxn=-1,ans;
int Time;
for(int k=1; k<=n; ++k)
{
T=T-t1;//计算剩余时间
ans=0;
size=0;//一定要归零
for(int i=1; i<=k; ++i)
{
a[i].fish=f[i];
a[i].num=l[i];
put(a[i]);
}
Time=T;
while(Time>0&&a[1].fish>0)
{
ans+=a[1].fish;
a[1].fish-=a[1].num;//减少该鱼塘每分钟的钓鱼量
get();//更新堆
Time--;//减少时间
}
maxn=max(maxn,ans);//寻找钓鱼最多的方法
t1=t[k];//记录穿越鱼塘的时间
}
cout<<maxn;
return 0;
}
//完美的代码