1859: Gone Fishing

Description

    John is going on a fishing trip. He has h hours available ( 1 <= h <= 16 ), and there are n lakes in the area (2 <= n <= 25), L1

, ..., Ln , all reachable along a single, one-way road. John starts at lake 1, but he can finish at any lake he wants. He can only travel from one lake to the next one, but he does not have to stop at any lake unless he wishes to. For each i = 1, ..., n-1, the number of 5-minute intervals it takes to travel from Li to Li+1 is denoted ti (0 < ti <= 192). For example, t3 = 4 means that it takes 20 minutes to travel from L3 to L4 .
    To help plan his fishing trip, he has gathered some information about the lakes. For each lake Li , the number of fish expected to be caught in the initial 5 minutes, denoted Fi ( Fi >= 0), is known. Each 5 minutes of fishing decreases the number of fish expected to be caught in the next 5-minute interval by a constant rate of di ( di >= 0). If the number of fish expected to be caught in an interval is less than di

, there will be no more fish left in the lake in the next interval. To simplify the planning, John assumes that no one else will be fishing at the lakes to affect the number of fish in the lakes.
    Write a program to help John plan his fishing trip to maximize the number of fish expected to be caught. The number of minutes spent fishing at each lakemust be a multiple of 5.

Input

You will be given a number of cases in the input. Each case starts with a line containing n. This is followed by a line containing h. This is followed by a line of n integers specifying Fi

(i = 1, ..., n), followed by a line of n integers di (i = 1, ..., n), and finally, a line of n-1 integers ti

(i = 1, ..., n-1). Input is terminated by a case in which n = 0.

Output

For each test case, print the number of minutes spent fishing at each lake, separated by commas, for the plan achieving the maximum number of fish expected to be caught (you should print the entire plan on one line even if it exceeds 80 characters). This is followed by a line containing the number of fish expected. If multiple plans exist, choose the one that spends as long as possible at L1

, even if no fish are expected to be caught in some intervals. If there is still a tie, choose the one that spends as long as possible at L2

, and so on. Insert a blank line between cases.

Sample Input

2 
1
10 1
2 5 
2
4
4
10 15 20 17
0 3 4 3
1 2 3
4
4
10 15 50 30 
0 3 4 3
1 2 3
0

Sample Output

45, 5
Number of fish expected: 31

240, 0, 0, 0
Number of fish expected: 480

115, 10, 50, 35
Number of fish expected: 724

Hint

Source

1999 Pacific NW Regional Contest

题目大意:
给你n个鱼塘,然后给你总时间(小时),然后给你每个鱼塘的第一次可以钓鱼的数量(没五分钟),然后给你每个鱼塘每次递减的数量,比如2的意思是说,每次可以钓的数量减二,然后给你从第i个鱼塘到第i+1鱼塘所花费的时间,问能最大钓多少鱼,以及在每个鱼塘停留的时间。
思路
比赛的时候我们队是用dp写的越写越乱  是ljb的思路,一直连样例都过不了,我是想用记忆化搜索写的,也没尝试,按道理这两种思路都应该是可以的,可能由于我们太菜,没能a掉,其实仔细想想可以用枚举加贪心写,因为题目限定必须从第一个开始出发依次到下一个,容易想到,我们可以枚举1~i这个区间,然后减去赶路的时间,然后用贪心的思路取此时每五分钟能调最多的鱼数量的鱼塘,为什么可行呢,可以想到我们枚举的是所有的可能,在每次可能中我们先减去赶路的时间,就不用考虑赶路的时间,也不用考虑钓鱼先后顺序了,因为题目要求只能从左到右钓鱼,而我们减去了赶路的时间,就相当于几个鱼塘合并成了一个鱼塘,对吧,但是这个鱼塘有几个分支,然后我们在这几个分支的无顺序挑选,其实和几个鱼塘的顺序挑选是一样的,比如先在第三个鱼塘挑选2次后此次最大值变为第二个鱼塘,那我们又去第二个鱼塘,然后最大值变成了第三个鱼塘,再去第三个鱼塘,这样的选择其实跟从左到右的顺序是一样的。
ac代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<sstream>
#include<set>
#include<map>
#include<vector>
#include<set>
using namespace std;
const int maxn=25+5;
int n,toalltime;
int fishBone[maxn],cost[maxn],finalTime[maxn];
struct node
{
    int fishes;
    int id;
    int theMinus;
    node(int fishes=0,int id=0,int theMinus=0):fishes(fishes),id(id),theMinus(theMinus){};
    bool operator <(const node& p) const
    {
        return fishes>p.fishes||(fishes==p.fishes&&id<p.id);
    }
}t[maxn];
int main()
{
    while(~scanf("%d",&n))
    {
        if(!n)
        return 0;
        int ans=-1;
        scanf("%d",&toalltime);
        toalltime*=60;
        memset(fishBone,0,sizeof(fishBone));
        for(int i=0;i<n;i++)
        {
            int x;
            scanf("%d",&x);
            t[i].id=i;
            t[i].fishes=x;
        }
        for(int i=0;i<n;i++)
        {
            int x;
            scanf("%d",&x);
            t[i].theMinus=x;
        }
        for(int i=0;i<n-1;i++)
        {
            scanf("%d",&cost[i]);
        }
        int tmptime[maxn];

        int tmpsum=0;
        for(int i=0;i<n;i++)
        {
        int tmptoall=toalltime;
        tmpsum=0;
        memset(tmptime,0,sizeof(tmptime));
        set<node>Q;
            for(int j=i;j>=0;j--)
            {
                if(j-1>=0)
                tmptoall-=(cost[j-1]*5);

                Q.insert(t[j]);
            }
            while(tmptoall)
            {
                node first=*Q.begin();
                Q.erase(Q.begin());
                tmpsum+=first.fishes;
                first.fishes-=first.theMinus;
                if(first.fishes<0)
                    first.fishes=0;
                Q.insert(first);
                tmptime[first.id]+=5;
                tmptoall-=5;
                if(tmptoall<5)
                    tmptoall=0;
            }
            if(tmpsum>ans)
            {
                ans=tmpsum;
                memcpy(fishBone,tmptime,sizeof(tmptime));
            }
        }
        for(int i=0;i<n;i++)
        {
            printf("%d%s",fishBone[i],i==n-1?"\n":", ");
        }
        cout<<"Number of fish expected: "<<ans<<endl;
        cout<<endl;
   }
   return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值