鱼塘钓鱼(fishing)

给出一个截止时间T(T<1000),设计一个钓鱼方案,从第1个鱼塘出发,希望能钓到最多的鱼。
  假设能钓到鱼的数量仅和已钓鱼的次数有关,且每次钓鱼的时间都是整数分钟。
【输入格式】
  输入文件共5行,分别表示:
  第1行为N;
  第2行为第1分钟各个鱼塘能钓到的鱼的数量,每个数据之间用一空格隔开;
  第3行为每过1分钟各个鱼塘钓鱼数的减少量,每个数据之间用一空格隔开;
  第4行为当前鱼塘到下一个相邻鱼塘需要的时间;
  第5行为截止时间T;
【输出格式】
  输出文件仅一个整数(不超过231-1),表示你的方案能钓到的最多的鱼。
【输入样例】
5
10 14 20 16 9
2 4 6 5 3
3 5 4 4
14
【输出样例】
   76
【知识准备】
最优化原理、贪心法、动态规划、用堆结构实现贪心。
【问题分析】
算法一:
我们可以这样想:如果知道了取到最大值的情况下,人最后在第i个鱼塘里钓鱼,那么用在路上的时间是固定的,因为我们不会先跑到第i个鱼塘里钓一分钟后再返回前面的鱼塘钓鱼,这样把时间浪费在路上显然不划算,再说在你没到某个鱼塘里去钓鱼之前,这个塘里的鱼也不会跑掉(即数量不会减少)。所以这时我们是按照从左往右的顺序钓鱼的,也可以看成路上是不需要时间的,即人可以自由在1~i个鱼塘之间来回走,只要尽可能选取钓到的鱼多的地方就可以了,这就是我们的贪心思想。其实,这个贪心思想并不是模拟钓鱼的过程,只是统计出在各个鱼塘钓鱼的次数。程序实现时,只要分别枚举钓鱼的终
点鱼塘(从鱼塘1到鱼塘n),每次按照上述贪心思想确定在哪些鱼塘里钓鱼,经过n次后确定后最终得到的一定是最优方案。

#include<iostream>
#include<cstdio>
using namespace std;
int a[105],b[105],c[105],v[105];
int main()
{  freopen("fishing.in","r",stdin);
   freopen("fishing.out","w",stdout);
   int n;
   cin>>n;
   for (int i=1;i<=n;++i)
   {  cin>>a[i];
   }
   for (int i=1;i<=n;++i)
   cin>>b[i];
   for (int i=1;i<=n-1;++i)
   {  cin>>c[i];
      c[i]=c[i]+c[i-1];
        }
   int maxxx=0;
   int t;cin>>t;
   for (int i=1;i<=n;++i)
   {  int s=t;
      s=s-c[i-1];
      int ans=0;
      for (int j=1;j<=i;++j)
        v[j]=a[j]+b[j];
      for (int j=1;j<=s;++j)
     {  int maxx=0,xh,y;
        for (int k=1;k<=i;++k)
        {  y=v[k]-b[k];
           if (y>maxx)
          { maxx=y;
            xh=k;
          }
        }
        v[xh]=v[xh]-b[xh];
        ans+=maxx;
     }
     maxxx=max(maxxx,ans);
   }
   cout<<maxxx;
}

算法二:
  其实,这道题是考虑最优性问题的,所以我们也可以用动态规划来解决,假设用Opt[t][n]来表示第t分钟时,人在第n个鱼塘里钓鱼,最多所能钓到的鱼数。则:
  Opt[t][n] =Maxinum{Opt[t-k][n-1]+S};
  穷举k,S为t-k+1到t之间,除去从第n-1的鱼塘走到第n个鱼塘的时间,在第n个鱼塘中可以钓到的鱼数。
算法三:
  建立以fish为关键字的大根堆,包括能钓到鱼的数量和池塘的编号。然后借助枚举创造条件,实现复杂度为O(m*nlogn)的算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值