【题目链接】

ybt 1373:鱼塘钓鱼(fishing)

【题目考点】

1. 动态规划:区间动规

2. 贪心 优先队列

【解题思路】

解法1:区间动规

该人只会从编号小的鱼塘走到编号大的鱼塘,不存在往回走的情况(从编号大的鱼塘走到编号小的鱼塘)。

  • 如果他仅仅往回走但不在任何鱼塘停留,那么这与不往回走钓到的鱼的数量相同,往回走是不必要的。
  • 如果存在往回走的情况,那么一定存在该人从某个第 x x x号鱼塘走回到第 y y y号鱼塘,其中 y < x y<x y<x,而且在第 y y y号鱼塘停留 t y t_y ty​分钟钓鱼。
  • 该情况可以由以下走法替代:先走到第 y y y号鱼塘,停留 t y t_y ty​分钟钓鱼,而后走到第 x x x号鱼塘。这样做还能省下往回走的时间。

1. 状态定义

  • 集合:钓鱼方案
  • 限制:最远走到第几个鱼塘,经过总时间
  • 属性:钓鱼数量
  • 条件:最大
  • 统计量:钓鱼数量

状态定义dp[i][j]:最远走到第i鱼塘,消耗时间j,可以钓到鱼的最大数量。
初始状态dp[0][j]=0:在前0个鱼塘中钓鱼,消耗时间j,可以钓到鱼的最大数量为0。

2. 状态转移方程

  • 集合:最远走到第i鱼塘,消耗时间j的钓鱼方案数。
  • 分割集合:根据在第i个鱼塘钓鱼的时间来分割集合

记在第i鱼塘第1分钟能钓到的鱼为fish[i],第i鱼塘每分钟鱼减少量为de[i]
可以预处理出在第i鱼塘钓鱼j分钟能钓到的鱼为f[i][j]以及在第i鱼塘能钓到鱼的最大时间mxTime[i]

f[i][0] = 0;
for(int j = 1; fish[i] > 0; j++)
{f[i][j] = f[i][j-1] + fish[i];fish[i] -= de[i];mxTime[i] = j;
}

第i鱼塘走到第i+1鱼塘的时间为t[i],用求前缀和的方法预处理出从第1鱼塘走到第i鱼塘(只走路不钓鱼)的时间st[i]

总使用时间j,从第i-1鱼塘出发到第i鱼塘消耗时间t[i-1],那么走到第i鱼塘后,剩余可分配的时间为j-t[i-1]

  • 如果在第i鱼塘钓鱼0分钟,那么在前i-1个鱼塘消耗的时间为j-t[i-1],最大钓鱼数量dp[i][j] = dp[i-1][j-t[i-1]]
  • 如果在第i鱼塘钓鱼1分钟,那么在前i-1个鱼塘消耗的时间为j-t[i-1]-1,最大钓鱼数量dp[i][j] = dp[i-1][j-t[i-1]-1]+f[i][1]
  • 如果在第i鱼塘钓鱼2分钟,那么在前i-1个鱼塘消耗的时间为j-t[i-1]-2,最大钓鱼数量dp[i][j] = dp[i-1][j-t[i-1]-2]+f[i][2]
  • 如果在第i鱼塘钓鱼k分钟,那么在前i-1个鱼塘消耗的时间为j-t[i-1]-k,最大钓鱼数量dp[i][j] = dp[i-1][j-t[i-1]-k]+f[i][k]
    k的最小值为0,最大时为mxTime[i],超过该时间就钓不到鱼了。同时k要满足小于等于总时间j减去从第1鱼塘一直不钓鱼走到第i鱼塘的时间st[i],即k <= j-st[i]
  • 以上所有情况取最大值

最远走到哪个鱼塘,都可能钓到最多的鱼。
记输入的总鱼塘数量为n,截止时间为endT,
最后求dp[1][endT], dp[2][endT], ..., dp[n][endT]中的最大值,就是最大钓鱼数量。

解法2:贪心

假定最远走到第i个鱼塘,由于不用走回头路,因此花费在路上的时间已经确定了。而后安排在各个鱼塘钓鱼的时间。
假想现在要画一个表格,示例如下:

鱼塘1 鱼塘2 鱼塘n
1+1 1
  • 选择当前各个鱼塘中钓鱼1分钟能钓到最多鱼的鱼塘,记录要在这个鱼塘钓鱼1分钟。
    在该鱼塘钓鱼1分钟后,该鱼塘下一分钟能钓到的鱼会减少。更新该鱼塘1分钟钓鱼获得的鱼的数量。
  • 而后再在当前各个鱼塘中选择钓鱼1分钟能钓到最多鱼的鱼塘,记录要在这个鱼塘钓鱼1分钟。而后更新该鱼塘每分钟钓鱼数量。
  • 重复此过程,直到所有时间都已分配。
  • 根据表格中的记录,得知在每个鱼塘的总钓鱼时间

实际执行过程为:从第1鱼塘开始向第i鱼塘走,到第x鱼塘时,在第x鱼塘钓鱼时间为记录中在第x鱼塘的总钓鱼时间,直到走到鱼塘i。
总钓鱼数量为:在执行记录的过程中,记录了的每分钟钓鱼数量的加和。
选择“能钓到最多鱼的鱼塘”的过程,可以使用优先队列来完成,使用优先队列求最值的复杂度为 O ( l o g n ) O(logn) O(logn)
最远走到的鱼塘从1循环到i,求出每种情况下的总钓鱼数量,比较得到最大值,即为结果。

【题解代码】

解法1:区间动规

#include <bits/stdc++.h>
using namespace std;
#define N 105
#define T 1005
int dp[N][T];//dp[i][j]:在前i个鱼塘中钓鱼,消耗时间j,可以钓到鱼的最大数量。
int fish[N], de[N], f[N][T], t[N], st[N], mxTime[N];
int n, endT, mxFish;
int main()
{cin >> n;//n:鱼塘数量 for(int i = 1; i <= n; ++i)cin >> fish[i];//fish[i]:第1分钟第i鱼塘可以钓到的鱼的数量for(int i = 1; i <= n; ++i)cin >> de[i];//dec[i]:每过一分钟鱼可以钓到的鱼减少的数量for(int i = 1; i <= n; ++i)for(int j = 1; fish[i] > 0; ++j){f[i][j] = f[i][j-1] + fish[i];//f[i][j]:在第i鱼塘钓鱼j分钟能钓到的鱼fish[i] -= de[i];mxTime[i] = j;//mxTime[i]:在第i鱼塘能钓到鱼的最大时间(超过这一时间就钓不到鱼了) }for(int i = 1; i <= n-1; ++i){cin >> t[i];//t[i]:从第i鱼塘走到第i+1鱼塘的时间st[i+1] = st[i] + t[i];//st[i]:从第1鱼塘走到第i鱼塘的时间 }cin >> endT;//endT:截止时间 for(int i = 1; i <= n; ++i)//i:鱼塘号 for(int j = 1; j <= endT; ++j)//j:消耗时间 for(int k = 0; k <= mxTime[i] && k <= j-st[i]; ++k)//k:在第j鱼塘钓鱼k分钟 dp[i][j] = max(dp[i][j], dp[i-1][j-t[i-1]-k] + f[i][k]);for(int i = 1; i <= n; ++i)mxFish = max(mxFish, dp[i][endT]);cout << mxFish;return 0;
}

解法2:贪心

#include <bits/stdc++.h>
using namespace std;
#define N 105
int fish[N], de[N], st[N], f[N];
int n, te, endT, mxFish;
struct Cmp
{bool operator () (int a, int b){return f[b] > f[a];//鱼塘每分钟钓鱼数量更高的鱼塘更优先 }
};
int main()
{cin >> n;//n:鱼塘数量 for(int i = 1; i <= n; ++i)cin >> fish[i];//fish[i]:第1分钟第i鱼塘可以钓到的鱼的数量for(int i = 1; i <= n; ++i)cin >> de[i];//dec[i]:每过一分钟鱼可以钓到的鱼减少的数量for(int i = 1; i <= n-1; ++i){cin >> te;//te:从第i鱼塘走到第i+1鱼塘的时间st[i+1] = st[i] + te;//st[i]:从第1鱼塘走到第i鱼塘的时间 }cin >> endT;//endT:截止时间for(int i = 1; i <= n; ++i)//最远走到第i鱼塘{memcpy(f, fish, sizeof(fish));//f[i]:临时保存第i鱼塘每分钟钓鱼数量 priority_queue<int, vector<int>, Cmp> pq;//优先队列中保存的是鱼塘编号,每分钟钓鱼数量更高的更优先 for(int j = 1; j <= i; ++j)pq.push(j);int fishNum = 0;//可分配时间为总时间减去走到鱼塘i的时间  fishNum:钓到的鱼数量 for(int t = 1; t <= endT-st[i]; ++t){if(pq.empty())break;int mxi = pq.top();//当前每分钟钓鱼数量最大的鱼塘编号 pq.pop();fishNum += f[mxi];//总钓鱼数量增加f[mxi]f[mxi] -= de[mxi];//该鱼塘每分钟钓鱼数量减少if(f[mxi] > 0)//如果在该鱼塘还能钓鱼 pq.push(mxi); //把该鱼塘加入到优先队列 }mxFish = max(mxFish, fishNum);//更新最大钓鱼数量 }cout << mxFish;return 0;
}

信息学奥赛一本通 1373:鱼塘钓鱼(fishing)相关推荐

  1. SSL 2331 洛谷 1717 信息学奥赛一本通 1373 鱼塘钓鱼#贪心#

    动态规划 温馨提示:交洛谷请在总时间*12并调整输入格式. 题目 设计一个钓鱼方案,从第1个鱼塘出发,希望能钓到最多的鱼. 分析 首先是贪心,最后在第i个鱼塘钓鱼的话,那么路上的时间是固定的,所以也可 ...

  2. 信息学奥赛一本通 1373池塘钓鱼

    池塘钓鱼 题目:http://ybt.ssoier.cn:8088/problem_show.php?pid=1373 好吧,在堆类型的题中我看到这道题第一个想到的居然是动态规划-- 1.DP 状态转 ...

  3. 1373:鱼塘钓鱼(fishing)——优先队列+贪心

    [题目描述] 有N个鱼塘排成一排(N<100),每个鱼塘中有一定数量的鱼,例如:N=5时,如下表: 即:在第1个鱼塘中钓鱼第1分钟内可钓到10条鱼,第2分钟内只能钓到8条鱼,--,第5分钟以后再 ...

  4. 信息学奥赛一本通(基础算法与数据结构-题解汇总目录)

    信息学奥赛一本通(C++版)在线评测系统 基础(二)基础算法   更新中...... 第一章高精度计算 1307[例1.3]高精度乘法 1308[例1.5]高精除 1309[例1.6]回文数(Noip ...

  5. 信息学奥赛一本通 (C++)上机练习

    信息学奥赛一本通(C++)上机练习 此书为娃儿的第一本刷题书.娃儿现在四年级 ,希望他能坚持下来.特开贴加油 luogu: disangan223 第一部分 C++语言 第一章 C++语言入门 T10 ...

  6. 信息学奥赛一本通_长乐一中老师演绎“奥赛传奇”

    董永建(右一)在课堂上. 台海网5月14日讯 据福州晚报报道,长乐一中有一位"传奇"老师--15年来,他辅导的学生在全国高中生信息学奥赛中获金牌3人次.银牌3人次.铜牌5人次:在全 ...

  7. 信息学奥赛一本通 提高篇 第5章 矩阵乘法

    例1 矩阵AXB 信息学奥赛一本通(C++版)在线评测系统 [矩阵乘法]矩阵A×B_Uletay-CSDN博客 矩阵乘法--矩阵A×B_vina的博客-CSDN博客 一本通1641[例 1]矩阵 A× ...

  8. 《信息学奥赛一本通提高篇》第6章 组合数学

    例1 计算系数(NOIP2011提高) 信息学奥赛一本通(C++版)在线评测系统 NOIP2011计算系数_nanhan27的博客-CSDN博客 「NOIP2011」 计算系数 - 组合数_TbYan ...

  9. 《信息学奥赛一本通 提高篇》

    提高篇 第一部分 基础算法 第1章 贪心算法 提高篇 第一部分 基础算法 第1章 贪心算法_青少年趣味编程-CSDN博客 提高篇 第一部分 基础算法 第1章 贪心算法 提高篇 第一部分 基础算法 第1 ...

最新文章

  1. 一文深入了解 Redis 内存模型,Redis 的快是有原因的!
  2. 信息化管理系统,团队效能提升的潜在价值
  3. java 获取jsp路径_java如何获取jsp页面上传的文件路径
  4. 【大数据分析常用算法】1.二次排序
  5. 论机智,还是国产安卓旗舰花样多,从2999到10999元,各有各的“开窍点”
  6. 一般性网络错误 请检查网络文档_如何编写好的软件设计文档
  7. 解决Button设置disabled后无法执行后台代码问题
  8. 在matlab中怎么录制音频_怎么录制淘宝页面中的视频?简单方法,轻松搞定
  9. 【DP】【树状数组】方伯伯的玉米田/优美玉米(luogu 3287/金牌导航 数据结构优化DP-5)
  10. 计算机英语讲课笔记03
  11. Jquery制作另一个炫丽广告栏-(VS2010版本)
  12. lisp 提取字符串中的數字_Redis 数据结构之字符串的那些骚操作
  13. matlab 发动机万有特性,用MATLAB语言绘制发动机万有特性的两种方法
  14. 通过XShell远程连接Linux
  15. pyqt5设置dialog的标题_PyQt5教程——对话框(6)
  16. 在Vmplayer中自定义桥接网络(Bridged Network)的配置
  17. 作为一只爬虫,如何科学有效地处理短信验证码?
  18. 虚拟服务器共享文件设置,虚拟机共享文件夹设置流程
  19. 计算机属性资源管理器已停止工作,windows资源管理器已停止工作,教您windows资源管理器已停止工作如何解决...
  20. 网络服务器未运行是什么原因是,Win7系统网络诊断提示诊断策略服务未运行怎么办?...

热门文章

  1. hive常用的几个日期处理
  2. 开源b2b2c商城系统具有的优势
  3. Linux正则表达式、grep、sed、awk简单使用
  4. 有此神器,神经影像配准不再需要高分辨3D T1w
  5. 轻量级Kubernetes-K3S简介入门
  6. 元宇宙3D虚拟数字人形象设计开发及方案
  7. 使用IDEA的Redis插件连接Redis服务器
  8. 前端开发HTML-HTML初识
  9. 解决 RIDE 执行输出日志中文乱码(RIDE 1.7.4.2)
  10. C语言 猜数字游戏 VS2022