钓鱼

【题目描述】
话说发源于小朋友精心设计的游戏被电脑组的童鞋们藐杀之后非常不爽,为了表示安慰和鼓励,VIP999决定请他吃一次“年年大丰收”,为了表示诚意,他还决定亲自去钓鱼,但是,因为还要准备2013NOIP,z老师只给了他H(1<=H<=24)个小时的空余时间,假设有N(2<=n<=100)个鱼塘都在一条水平路边,从左边到右编号为1、2、3、。。。、n)。VIP是个很讲究效率的孩子,他希望用这些时间钓到尽量多的鱼。他从湖1出发,向右走,有选择的在一些湖边停留一定的时间钓鱼,最后在某一个湖边结束钓鱼。他测出从第I个湖到I+1个湖需要走5*ti分钟的路,还测出在第I个湖边停留,第一个5分钟可以钓到鱼fi,以后再每钓5分钟鱼,鱼量减少di。为了简化问题,他假定没有其他人钓鱼,也不会有其他因素影响他钓到期望数量的鱼。请编程求出能钓最多鱼的数量。
【输入格式】
第一行:湖的数量n。
第二行:时间h(小时)。
第三行:n个数,f1,f2,…fn。
第四行:n个数,d1,d2,….dn。
第五行:n-1个数,t1,t2,….tn-1
【输出格式】
一个数,所能钓鱼的最大数量。
【样例输入】
2
1
10 1
2 5
2
【样例输出】
31
【分析】
首先确定VIP999不可能走回头路,因为这样还不如走过去之前就钓。
设f[i]表示前i个鱼塘能钓到最多的鱼数。

var
  t,f,f1,d:array[0..1001]of longint;
    i,j,k,n,ti,h,ans,p,s:longint;
begin
  read(n);
    read(h);
    h:=h*12;
    for i:=1 to n do read(f[i]);
    for i:=1 to n do read(d[i]);
    for i:=1 to n-1 do read(t[i]);
    ans:=-1;
    for i:=1 to n do begin
      f1:=f;
      h:=h-t[i-1];
        s:=0;
        for j:=1 to h do begin
          ti:=-maxlongint;
            for k:=1 to i do
              if f1[k]>ti then begin
                  ti:=f1[k];
                    p:=k;
                end;
            s:=s+f1[p];
            f1[p]:=f1[p]-d[p];
            if f1[p]<0 then f1[p]:=0;
        end;
        if s>ans then ans:=s;
    end;
    write(ans);
end.

转载于:https://www.cnblogs.com/JRX2015U43/p/6533456.html

### 动态规划解决约翰钓鱼问题 约翰钓鱼问题可以通过动态规划(Dynamic Programming, DP)来解决。问题的核心在于如何在有限时间内最大化钓鱼的数量,同时考虑每个池塘的上鱼率递减特性。 #### 问题建模 1. **状态定义** 定义 `dp[i][j]` 表示在前 `i` 个池塘中,约翰使用了 `j` 单位时间的最大钓鱼数量[^1]。 2. **转移方程** 假设从第 `k` 个池塘到第 `i` 个池塘需要花费 `T[k][i]` 的时间,则有以下关系: ```plaintext dp[i][j] = max(dp[i][j], dp[k][j - T[k][i]] + fish(k, i)) ``` 其中 `fish(k, i)` 表示从第 `k` 个池塘到第 `i` 个池塘后,在第 `i` 个池塘钓鱼所能获得的最大数量。需要注意的是,由于每个池塘的上鱼率递减,因此需要重新排列钓鱼顺序以最大化收益[^1]。 3. **初始条件** 初始时,`dp[0][j] = 0`,表示没有池塘时钓鱼数量为零。 4. **目标函数** 最终的目标是求解: ```plaintext max(dp[n][j]) for j in [0, h * 12] ``` 这里的 `h * 12` 是将小时转换为单位时间(每单位时间为5分钟)。 #### 算法实现 以下是基于动态规划的算法实现代码: ```python def max_fish(h, n, fish_rate, travel_time): # 将小时转换为单位时间(每单位时间5分钟) total_time = h * 12 # 初始化DP表 dp = [[0] * (total_time + 1) for _ in range(n + 1)] # 预处理每个池塘的钓鱼收益(考虑到上鱼率递减) def calculate_fish(i, t): count = 0 fish = 0 rate = fish_rate[i - 1] while count < t and rate > 0: fish += rate rate -= 1 # 上鱼率递减 count += 1 return fish # 动态规划填表 for i in range(1, n + 1): for j in range(total_time + 1): dp[i][j] = dp[i - 1][j] # 不在当前池塘钓鱼 for k in range(j + 1): # 枚举到达当前池塘的时间 if k >= travel_time[i - 1]: # 确保有足够时间到达 fishing_time = j - k if fishing_time >= 0: dp[i][j] = max(dp[i][j], dp[i - 1][k] + calculate_fish(i, fishing_time)) return max(dp[n][j] for j in range(total_time + 1)) # 示例输入 h = 2 # 总时间2小时 n = 3 # 3个池塘 fish_rate = [5, 4, 3] # 每个池塘的初始上鱼率 travel_time = [0, 1, 2] # 到达每个池塘所需时间(单位时间) # 输出最大钓鱼数量 print(max_fish(h, n, fish_rate, travel_time)) ``` #### 算法复杂度分析 - **时间复杂度**:`O(n * T^2)`,其中 `n` 是池塘数量,`T` 是总时间单位数。由于需要枚举每个池塘和每个时间点,复杂度较高。 - **空间复杂度**:`O(n * T)`,用于存储动态规划表。 #### 注意事项 - 钓鱼次序在计算中可以忽略先后顺序,因为已经支付了路上耗时,剩余时间内的钓鱼次序不影响结果[^2]。 - 上鱼率递减需要在每次钓鱼后更新,确保收益最大化。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值