黑书贪心例题之钓鱼 poj1042:Gone Fishing

总时间限制: 2000ms 内存限制: 65536kB
描述
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) 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 lake i to lake i + 1 is denoted ti (0 < ti <=192). For example, t3 = 4 means that it takes 20 minutes to travel from lake 3 to lake 4. To help plan his fishing trip, John has gathered some information about the lakes. For each lake i, 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 or equal to 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 he expects to catch.
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 at each lake must be a multiple of 5.
输入
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. Next, there is a line of n integers specifying fi (1 <= i <=n), then a line of n integers di (1 <=i <=n), and finally, a line of n - 1 integers ti (1 <=i <=n - 1). Input is terminated by a case in which n = 0.
输出
For each test case, print the number of minutes spent 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 lake 1, 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 lake 2, and so on. Insert a blank line between cases.
样例输入
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
样例输出
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
来源
East Central North America 1999

本题详细思路可以从黑书上得出,使用贪心法可解,但是有一个问题有没搞懂,黑书上写到普通的算法O(kn^2)的复杂度,没有问题,但是用堆为何就降为了O(knlogn)?

假设使用堆的话,那么一共n次枚举,而每一次枚举中,有k次从堆中取出最小值,但是每次枚举还需要话费时间来建堆,如果只算取最小值的时间复杂度,那么确实是O(knlogn),但是每一次枚举的过程中如果算上建堆的nlogn的时间的话,那么得出的复杂度结果应该是O( n(klogn+nlogn) ) 因为k<n,可以得出复杂度应该为O(n^2 * logn)才对。

故我使用了最朴素的遍历的方法来取最小值AC了本题。

贴上代码

#include <iostream>
#include <stdio.h>
#include <memory.h>

using namespace std;
int n;
int coun[26] = {0}, temp[26]={0}, sum = 0;
int f[26],d[26],t[26];
int h = 0;

int main()
{
    while(cin>>n)
    {
        if(n == 0)
            break;
        memset(f,0,sizeof(f));
        memset(d,0,sizeof(d));
        memset(t,0,sizeof(t));
        scanf("%d",&h);
        h *= 12;
        for(int i = 0; i < n; i ++)
            scanf("%d",&f[i]);
        for(int i = 0; i < n; i ++)
            scanf("%d",&d[i]);
        for(int i = 0; i < n-1; i ++)
            scanf("%d",&t[i]);
        memset(coun,0,sizeof(coun));

        sum = -1;
        for(int i = 0; i < n; i ++)
        {
            memset(temp,0,sizeof(temp));
            int tim = 0;
            for(int j = 0; j < i; j ++)
            {
                tim += t[j];
            }
            tim = h - tim;
            //printf("%d\n",tim);
            int tf[26];
            memcpy(tf,f,sizeof(tf));
            /*for(int i = 0; i <n; i++)
                printf("%d\n",tf[i]);
             */
            int ts = 0;
            for(int k = 0; k < tim; k ++)
            {
                int ti = 0; //compute the max lake
                int tn = 0; // the index
                for(int j = 0; j <= i; j ++)
                {    if( tf[j] > ti)
                {
                    ti = tf[j];
                    tn = j;
                }
                }
                if(ti == 0)
                {
                    temp[0] += tim - k;
                    break;
                }
                ts += ti;
                tf[tn] -= d[tn];
                if( tf[tn] < 0 )
                    tf[tn] = 0;
                temp[tn] ++;
            }
            if(ts > sum)
            {
                sum = ts;
                memcpy(coun,temp,sizeof(coun));
            }
        }
        printf("%d",coun[0]*5);
        for(int i = 1; i < n; i ++)
            printf(", %d",coun[i]*5);
        printf("\n");
        printf("Number of fish expected: %d \n\n",sum);
    }

    return 0;
}

本题要注意到一点点边界问题,我最开始的代码里,在每一次的case里,将sum初始值赋为了0,这会导致一种情况,如果给的例子里所有湖的鱼的数量都为0的话,那么由于if(ts>sum)这个条件(这个条件也不能改为等号,根据题意,在同等产量上应该是前面的湖花的时间尽量长,如果改为等号,则会使在后面湖花费更长时间的策略覆盖掉先前的策略),不会有任何计算结果来赋值给coun[26],输出就会是在每个湖上花的时间是0,而事实却不应该是这样,输出结果应该是在第一个湖上花了所有的时间。故将初始sum=-1.

黑书贪心例题之钓鱼 poj1042:Gone Fishing

时间: 2024-10-10 00:51:53

黑书贪心例题之钓鱼 poj1042:Gone Fishing的相关文章

POJ-1042 Gone Fishing (贪心法求最佳钓鱼方案

Gone Fishing Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 28075   Accepted: 8371 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) all reachab

黑书例题 Fight Club 区间DP

题目可以在bnuoj.soj等OJ上找到. 题意: 不超过40个人站成一圈,只能和两边的人对战.给出任意两人对战的输赢,对于每一个人,输出是否可能是最后的胜者. 分析: 首先序列扩展成2倍,破环成链. dp[i][j]表示i和j能够相遇对打,那么dp[i][i+n]为真代表可以成为最后胜者. 枚举中间的k,若i和j都能和k相遇,且i和j至少一人能打赢k,那么i和j可以相遇. 复杂度o(n^3) 1 #include<cstdio> 2 #include<cstring> 3 usi

黑书之1.2.6:离散数学

题目描述: 有一个函数,它的定义域:1 to N(2<=N<=100000),值域f(n)为long int(in C++)(最后证明在-2^31—2^31).要求函数上的两个点a,b使得当x∈(a,b)函数f,在直线ab的下方,并且要求ab的倾角最大. 根据黑书所说,O(n^2)的算法确实是很容易相出,但是存在一种O(n)算法.想了许久都不能明白,中间确实想到过最终的解法,但是没有仔细想,故没有证明其正确性,最终没有相处此题. 根据网上的同道中人所述,写出算法: 从左到右扫描,O(n)的时间

黑书练习题 更新中

1.4.7 奇数偶数 POJ 1733 Parity game 2.5.26 Unix 插头 POJ 1087 A Plug for UNIX 黑书练习题 更新中

POJ 1042 Gone Fishing (贪心)(刘汝佳黑书)

Gone Fishing Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 30281   Accepted: 9124 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) all reachab

【紫书】例题3-3 回文词(Palindromes, UVa401)

[题目描述] 输入一个字符串,判断它是否为回文串以及镜像串.输入字符串保证不含数字0.所谓回文串,就是反转以后和原串相同,如abba和madam.所有镜像串,就是左右镜像之后和原串相同,如2S和3AIAE.注意,并不是每个字符在镜像之后都能得到一个合法字符.在本题中,每个字符的镜像如图所示(空白项表示该字符镜像后不能得到一个合法字符). 输入的每行包含一个字符串(保证只有上述字符.不含空白字符),判断它是否为回文串和镜像串(共4种组合).每组数据之后输出一个空行. [样例输入] NOTAPALI

【紫书】例题3-6 环状序列(Circular Sequence, ACM/ICPC Seoul 2004, UVa1584)

[题目描述] 长度为n的环状串有n种表示法,分别为某个位置开始顺时针得到.例如,图中的环状串有10种表示: CGAGTCAGCT,GAGTCAGCTC,AGTCAGCTCG等.在这些表示法中,字典序最小的称为"最小表示". 输入一个长度为n(n<=100)的环状DNA串(只包含A.C.G.T这4种字符)的一种表示法,你的任务是输出该环状串的最小表示.例如,CTCC的最小表示是CCCT,CGAGTCAGCT的最小表示为AGCTCGAGTC. 输入: 在输入文件的第一行 为序列数量.

机试指南第二章-经典入门-贪心例题自解

例2.11 FatMouse's Trade 解题思路 贪心策略.每次都买剩余物品中性价比(即重量价格比)最高的物品,直到该物品被买完或者钱耗尽.若该物品已经被买完,则我们继续在剩余的物品中寻找性价比最高的物品 AC代码 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; struct Thing { double j;

bzoj2539 丘比特的烦恼、黑书P333 (最优二分图匹配)

丘比特的烦恼 题目描述 Description 随着社会的不断发展,人与人之间的感情越来越功利化.最近,爱神丘比特发现,爱情也已不再是完全纯洁的了.这使得丘比特很是苦恼,他越来越难找到合适的男女,并向他们射去丘比特之箭.于是丘比特千里迢迢远赴中国,找到了掌管东方人爱情的神--月下老人,向他求教. 月下老人告诉丘比特,纯洁的爱情并不是不存在,而是他没有找到.在东方,人们讲究的是缘分.月下老人只要做一男一女两个泥人,在他们之间连上一条红线,那么它们所代表的人就会相爱--无论他们身处何地.而丘比特的爱