TOJ 1163.Gone Fishing(经典题目)

题目链接

这道题没得说真的特别经典,枚举+贪心经典题目:首先lake数很少,故可以枚举出john最终停留在每个lake的钓鱼数。确定了john最终停留的lake数后,就可以利用贪心算法每次钓最多的鱼,注意:虽然lake是单线单行,但这并不影响每次取最大,因为实际中依次钓每个湖即可,这种抽象意义上 的贪心策略不好想,因此真的很经典!很经典!(重要的事说三遍)。
通过这道题真的可以学到很多知识,总结如下:

  • 采用优先队列可以每次找到最大的钓鱼数,学习了一下priority_queue,以及利用cmp修改排序规则,注意优先队列默认是最大堆。

  • PE了好几次,纠结了好久才发现是由于结果最后多输出了一个空行。

  • 还CE了一次。。。是由于提交到oj上时定义了一个非法的数组time[30],貌似这里time是保留字,但是我在dev上却编译通过了。

  • 题目要求在有多种可能的情况下要在尽量靠前的位置停留,所以在重载排序规则时要注意lake要从小到大

#include <stdio.h>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
int n=1,h,lake[30],ti[30],fish[30],di[30];
struct Node{
    int lable,fishNum;
    Node (int a=0,int b=0):
        lable(a),fishNum(b){} 
};
struct loadcmp{
    bool operator()(Node a,Node b){
        if(a.fishNum == b.fishNum) return a.lable > b.lable;
    return a.fishNum < b.fishNum;
    }
};
int fishing(int last)
{
    int times = h*12; int result = 0;
    memset(lake,0,sizeof(lake));
    for(int i=0;i<last;i++) times-=ti[i];
    priority_queue<Node,vector<Node>,loadcmp> que;
    for(int i=0;i<=last;i++){
        if(fish[i]>0){
            que.push(Node(i,fish[i]));
        }
    }
    Node node;
    while(times>0)
    {
        if(que.empty()) break;
        times--;
        node = que.top();
        que.pop();
        result+=node.fishNum;
        node.fishNum-=di[node.lable];
        if(node.fishNum>0) que.push(node);
        lake[node.lable]++;
    }
    return result;
}
int main()
{
    int flag=0;
    while(scanf("%d",&n)&& n)
    {
        if(flag)
            printf("\n");
        flag++;
        scanf("%d",&h);
        for(int i=0;i<n;i++)
            scanf("%d",&fish[i]);
        for(int i=0;i<n;i++)
            scanf("%d",&di[i]);
        for(int i=0;i<n-1;i++)
            scanf("%d",&ti[i]);
        int fishMax = 0,lake_count=0,current_fish;
        for(int i=0;i<n;i++){
            current_fish = fishing(i);
            if(current_fish > fishMax)
                {fishMax=current_fish;lake_count=i;}
        }
        int sum=0;
        fishing(lake_count);
        for(int i=0;i<n;i++)
            sum+=lake[i]*5;
        for(int i=0;i<lake_count;i++)
            sum+=ti[i]*5;
        sum= h*60-sum;
        cout<<lake[0]*5+sum;
        for(int i=1;i<n;i++)
            cout<<", "<<lake[i]*5;
        //printf("\nNumber of fish expected: %d\n",fishMax);
        cout<<'\n'<<"Number of fish expected: "<<fishMax<<endl;
    }
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值