POJ-1042-Gone Fishing-枚举+贪心

70 篇文章 0 订阅
12 篇文章 0 订阅

http://poj.org/problem?id=1042

题意:

给你n,表示n个池塘

给你h,表示你要钓鱼h小时

接下来n个数,f[i],表示第i个池塘一开始有 f[i]条鱼儿; (即使你钓了x条鱼,这个池塘的鱼儿数量不会变,还是f[i])

接下来n个数,d[i],表示第i个池塘每过5分钟,消失d[i]条鱼儿 (在有人钓鱼的情况下) (题设是有点不切实际,不用理)

接下来n-1个数,表示第i个池塘到第i+1个池塘所花的时间, (注意要从池塘1到池塘5,必须先经过2 3 4)


那么问你,在h小时得到最多的鱼数是多少,并输出在每个池塘所呆的时间。

如果鱼数相同,请输出序号小的池塘尽可能呆得时间多的答案;


直接从正面入手有点麻烦处理,只要是中间还要考虑移动的耗时;

因为最后停在哪个池塘的情况只有n种,

假设停在第i个池塘,我们就可以知道,最终在移动的过程总耗时必然为sum_t[i-1],

那么就剩下res_time=总时间-sum_t[i-1];

这些时间全部可以用来钓鱼,那么问题就简单多了;

我们把每个池塘,每次能钓到鱼(会递减)的数量都存起来,然后降序排序

我们只取前面的鱼来钓,直到res_time耗尽或者鱼全没了。

【要注意 d[i]=0的情况,某个池塘的鱼是不会递减的,要特别处理一下】

然后如果 在res_time还有的情况下,鱼钓完了,根据题目要求,要【序号小的池塘尽可能呆得时间多

那么我们把剩下的时间全部留在池塘1即可;


因此,我们枚举 最终停在池塘 1到n 的情况,就能得到答案了;



挫代码: 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
double eps=0.0000001;
struct node
{
	int val,id;
	node(){}
	node(int a,int b)
	{val=a;id=b;}
};
node tm[100005];
int cmp(node a,node b)
{
	if (a.val!=b.val)
		return a.val>b.val;
	else
		return a.id<b.id;
}

int f[30],d[30],t[30];
int sum_t[30];
int sum[30];
int ans_num[30]; 
int tmp_num[30];
int min(int a,int b){return a<b?a:b;}
int main()
{ 
	int i,j,k,n,h;
	int maxx;
	int cnt=1;
 
	while(cin>>n&&n)
	{
		maxx=-1;
		cin>>h;
		h*=12;
		for (i=1;i<=n;i++)
			scanf("%d",&f[i]);
		for (i=1;i<=n;i++)
			scanf("%d",&d[i]);
		for (i=1;i<=n-1;i++)
		{
			scanf("%d",&t[i]);
			sum_t[i]=sum_t[i-1]+t[i];		//移动耗时前缀和
		}
		
		int end;
		
		for (end=1;end<=n;end++)
		{
			int ok=0;
			int res_time=h-sum_t[end-1];  //除掉移动花费的时间,剩下的为可以钓鱼的时间
			
			for (i=1;i<=end;i++)	//把每一次耗时可能掉的鱼数都放到tm数组
			{
				int tmp=f[i];
				while(tmp>0)
				{
					tm[++ok].val=tmp;
					tm[ok].id=i;
					if (d[i]==0)  //当作能钓n次
					{
						for (j=1;j<=h;j++)
						{
							tm[++ok].val=tmp;
							tm[ok].id=i;
						}
						break;
					}
					tmp-=d[i];	
				}
			}
			sort(tm+1,tm+1+ok,cmp);	//降序排序
			int len=min(ok,res_time);	
			int ans=0;
			memset(tmp_num,0,sizeof(tmp_num));
			for (i=1;i<=len;i++)	
			{	
				ans+=tm[i].val;
				
					tmp_num[tm[i].id]++; 
			}
			if (ans>=maxx)		//大于等于都可能更新
			{
				if (res_time>ok)		//如果钓完了鱼还有剩余时间,就把时间全部浪费在第一个鱼塘
				{
				tmp_num[1]+=res_time-ok;	
				}
				int flag=0;
				if (ans==maxx)
				{
					for (i=1;i<=n;i++)		//按找题目要求,鱼数一样取在序号小的鱼塘花费时间较多的答案
					{
					if (tmp_num[i]==ans_num[i]) continue;
					if (tmp_num[i]<ans_num[i]) {flag=1;break;}
					if (tmp_num[i]>ans_num[i]) {flag=0;break;}
					}
				}
				if (flag) continue;
				maxx=ans;
				memset(ans_num,0,sizeof(ans_num));
				for (i=1;i<=n;i++)
					ans_num[i]=tmp_num[i]; 
		 	
			}
		 
		
		}
		
		 if (cnt!=1)printf("\n");
	    cnt++;
		for (i=1;i<=n;i++)
		{
			if (i!=1)		 printf(", ");
			printf("%d",5*ans_num[i]);
		}
		printf("\nNumber of fish expected: %d\n",maxx);
	
 	
	}
 
	return 0;
	
}






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值