【ACM】POJ 1042 Gone Fishing

本文介绍了一个基于枚举和贪心策略解决的最大钓鱼收益问题。通过枚举可达湖泊并使用贪心策略选择捕鱼最多的湖泊,实现了最大捕鱼量的计算。特别关注了路径限制条件下的最优解策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

    大概题意:约翰有h个小时可用来钓鱼,该区域有n个湖泊,第i个湖在最初的5分钟内捕获的鱼的数量是fi
鱼每过5分钟减少di条,如果预计在一段时间内捕获的鱼的数量小于或等于di,则在下一个时间段内湖中将不再有鱼。
湖泊沿着一条单向道路可达,对于每个湖,从湖i到湖i+1所需要的5分钟间隔为ti个(他可以在任意湖边停下)
求约翰最大能钓到的鱼的条数.
解题思路:(枚举+贪心)
    1.枚举约翰从第一个湖开始可以走到的终点
    2.将时间分成走路花的时间和钓鱼花的时间,每次计算时将走路花的时间扣除,即可视作瞬间到达
    3.每5分钟将所有湖以期望从大到小排序,每次挑选鱼最多的湖(贪心),进行计算,直至湖里没有鱼或者没有时间
注意事项:
    1.因为路为单向可达,故在选取期望最大的湖时,若有两湖或多湖期望相同,序号小的应优先考虑
    2.在对期望进行减法计算时,若期望相减之后为负数,应将其置为0
    3.若所有湖都没有鱼,且还有剩余时间,默认将剩余时间加到第一个湖上
    4.注意输出格式(粗心,报了很多次PE)
代码:

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node
{
	int f,d,p;
};
node lake[30];
int fi[30];
int time[30];
int sum[30];
int stay[30][30];
bool cmp(node a,node b)
{
	if(a.f==b.f)
		return a.p<b.p;
	return a.f>b.f;
}
int main()
{
	int n,h,h1;
	while(~scanf("%d",&n)&&n)
	{
		memset(time,0,sizeof(time));
		memset(sum,0,sizeof(sum));
		memset(stay,0,sizeof(stay));
		scanf("%d",&h);
		for(int i=0;i<n;i++)
		{
			scanf("%d",&lake[i].f);
			fi[i]=lake[i].f;
			lake[i].p=i;
		}
		for(int i=0;i<n;i++)
			scanf("%d",&lake[i].d);
		for(int i=1;i<n;i++)
			scanf("%d",&time[i]);
		int maxx=-1,sign=-1;
		//枚举终点
		for(int i=0;i<n;i++)
		{
			h1=h*60;//换算进制 
			for(int j=0;j<=i;j++)//走路的时间 
			h1-=time[j]*5;
			if(h1<=0)
			break;
			while(h1)
			{
				if(i!=0)
				{
					sort(lake,lake+i+1,cmp);//第一个湖为最多鱼的湖 
				}
				if(lake[0].f==0)
				break;
				else
				{
					sum[i]+=lake[0].f;//总和 
					stay[lake[0].p][i]+=5;//呆的时间 
					if(lake[0].f>lake[0].d)
						lake[0].f-=lake[0].d;
					else
						lake[0].f=0;
					h1-=5;
				}
			}
			if(h1>0)
			stay[0][i]+=h1;
			if(sum[i]>maxx)
			{
				maxx=sum[i];
				sign=i;
			} 
			for(int j=0;j<=i;j++)//重置 
			lake[j].f=fi[lake[j].p];
		}
		for(int i=0;i<n;i++)
		{
			printf("%d",stay[i][sign]);
			if(i!=n-1)
			printf(", ");
		}
		printf("\n");
		printf("Number of fish expected: %d\n",maxx);
		printf("\n");	
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值