POJ 1042 -Gone Fishing

这里写图片描述
这里写图片描述
题目链接

题目分析

题意

在一条水平路边,有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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值