NYOJ 30 && POJ 1042 Gone Fishing(枚举+贪心)

来源:互联网 发布:北京秦淮数据有限公司 编辑:程序博客网 时间:2024/05/19 15:19

【题目链接】:Click here~~

【题目大意】:

一个人去钓鱼,在一条单向路上的旁边有n个湖,并且从湖i到湖i+1需要ti的时间,每个湖里面有fi条鱼,每钓一次鱼,鱼会减少di条。在给定时间T内,问如何才能使钓的鱼最多,并记录在各个湖上停留的时间。

【解题思路】

此题细节处理好多麻烦,一定要认真看清题意,POJ WA了无数遍,纠结一天。参考了别人的题解,思路如下:

首先须注意的一点是,John只能向前走,返回的话只会增加John在路上的时间,因而减少他钓鱼的时间。因此此题解题步骤如下:
1、  枚举John经过的最后一个湖,每种情况减去所需步行的时间,剩下的就是钓鱼的时间。
2、  每5分钟选取钓鱼量最多的湖进行钓鱼,直到时间耗尽。
3、  在所有枚举的情况中选择钓鱼量最多的情况,即为问题的最优解。
此题需要注意的几个问题:
1、  如果解不唯一,选择在第一个湖耗时最多的解;如果仍旧存在不惟一解,选择在第二个湖耗时最多的解,以此类推。
2、  随着时间的增加,在某个湖中的钓鱼数可能会出现负数,此时应将该湖中每个时间单位的钓鱼数更新为零。
3、  在测试数据或程序运行的过程中可能出现每个湖鱼数全为0的情况,注意特别处理。

4、  枚举时,结束的标志是剩余时间<=0。

【source】黑书贪心第一题

代码:

#include <stdio.h>#include <math.h>#include <queue>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int maxn=30;#define bug  puts("AC >_<")int _time[maxn],ans[maxn],temp[maxn];struct node{     int FI,DI;}Lake[maxn],copyLake[maxn],Dist[maxn];int main(){    //freopen("1.txt","r",stdin);    int Lakenum,t,tot=0;    while(cin>>Lakenum&&Lakenum)    {        int Time;        cin>>Time;        Time=Time*60;        for(int i=0; i<Lakenum; i++) cin>>Lake[i].FI;       //输入FI        for(int i=0; i<Lakenum; i++) cin>>Dist[i].DI;     //输入DI        _time[0]=0;        for(int i=1; i<Lakenum; i++){            cin>>t;            _time[i]=_time[i-1]+t*5;            //每个湖的ti        }                                       //每五分钟选取钓鱼量最大的        memset(ans,0,sizeof(ans));        int Max=-1;        for(int i=0; i<Lakenum; i++){          //开始枚举终点的位置{            int sum=0,left_time=Time-_time[i];//总时间-路上消耗时间=该湖钓鱼的时间            memset(temp,0,sizeof(temp));             memcpy(copyLake,Lake,sizeof(Lake));//复制原先初始值            while(left_time>0)                //每个湖剩下的能钓鱼的时间,开始捕鱼            {                int maxx=0,id=0;                for(int j=0; j<=i; j++){                    if(copyLake[j].FI>maxx){   //第一轮判断哪个湖能捕到最多鱼                        maxx=copyLake[j].FI;                        id=j;                    }                }                if(maxx==0)                  //时间还剩余,鱼量已经捕完,直接跳出循环                    break;                sum+=maxx;                temp[id]+=5;                copyLake[id].FI-=Dist[id].DI;//鱼量依次递减                left_time-=5;            }            if(left_time>0)                  //时间还剩余!注意加到第一个湖!坑点!                temp[0]+=left_time;            if(sum>Max){                     //第二轮判断,所有枚举状态下捕鱼量最大!                Max=sum;                for(int j=0; j<=i; j++)                    ans[j]=temp[j];            }        }        if(tot>0)                           //输出格式            printf("\n");        printf("%d",ans[0]);        for(int i=1; i<Lakenum; i++)            printf(", %d",ans[i]);        printf("\n");        printf("Number of fish expected: %d\n",Max);        tot++;    }    return 0;}/*2110 12 524410 15 20 170 3 4 31 2 34410 15 50 300 3 4 31 2 30*/


0 0