题目分析
题意
在一条水平路边,有n个钓鱼湖,从左到右编号为1、 2 、3、…、n。John有h小时的空余时间,他希望用这些时间钓到尽量多的鱼。他从湖1出发,向右走,有选择的在一些湖边停留一定时间钓鱼,最后在某一湖边结束钓鱼。测出从第i个湖到第i+1个湖需要5×ti分钟,在第i个湖边停留,第一个5分钟可以钓到鱼fi,之后每5分钟钓鱼量减少di。没有其他影响因素的情况下,求钓鱼最多的方案。
思路
把钓5分钟鱼称为钓一次鱼。
采取贪心策略,每次选一个鱼最多的湖泊钓一次鱼。对于每个湖泊,任何时候钓鱼的数目只与在该湖里钓鱼的次数有关,与钓鱼的总次数无关。若所有的湖都已经空了,并且时间还有剩余,默认把剩余时间全部计入第一个湖的时间。
代码
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#define MAX 30
using namespace std;
struct node{
int id,fish,js,time;
friend bool operator <(const node&x,const node&y){
if(x.fish==y.fish)
return x.id>y.id;
return x.fish<y.fish;
}
}a[MAX];
priority_queue<node>q;
int n,h,ans[MAX],tmp[MAX],maxsum;
void greedy(){
int i,j;
maxsum=-1;
for(i=0;i<n;i++){
while(!q.empty())
q.pop();
for(j=0;j<=i;j++)
q.push(a[j]);
int lt=h-a[i].time,sum=0;
memset(tmp,0,sizeof(tmp));
while(lt>0){
node temp=q.top();
q.pop();
if(temp.fish<=0)
break;
sum+=temp.fish;
temp.fish-=temp.js;
tmp[temp.id]+=5;
q.push(temp);
lt-=5;
}
if(lt>0)
tmp[0]+=lt;
if(sum>maxsum){
maxsum=sum;
for(j=0;j<n;j++)
ans[j]=tmp[j];
}
}
}
int main(){
//freopen("TXA.txt","r",stdin);
int i,t,cas=0;
while(scanf("%d",&n),n){
scanf("%d",&h);
h*=60;
for(i=0;i<n;i++){
scanf("%d",&a[i].fish);
a[i].id=i;
}
for(i=0;i<n;i++)
scanf("%d",&a[i].js);
a[0].time=0;
for(i=1;i<n;i++){
scanf("%d",&t);
a[i].time=a[i-1].time+t*5;
}
if(cas>0)
printf("\n");
cas++;
greedy();
printf("%d",ans[0]);
for(i=1;i<n;i++)
printf(", %d",ans[i]);
printf("\nNumber of fish expected: %d\n",maxsum);
}
return 0;
}