1373:鱼塘钓鱼(fishing)

【算法分析】

解法1:区间动规
该人只会从编号小的鱼塘走到编号大的鱼塘,不存在往回走的情况(从编号大的鱼塘走到编号小的鱼塘)。

  • 如果他仅仅往回走但不在任何鱼塘停留,那么这与不往回走钓到的鱼的数量相同,往回走是不必要的。
  • 如果存在往回走的情况,那么一定存在该人从某个第x 号鱼塘走回到第y 号鱼塘,其中y < x ,而且在第y 号鱼塘停留t y 分钟钓鱼。
  • 该情况可以由以下走法替代:先走到第y 号鱼塘,停留t y 分钟钓鱼,而后走到第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]中的最大值,就是最大钓鱼数量。

【参考代码】

#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:贪心
假定最远走到第i个鱼塘,由于不用走回头路,因此花费在路上的时间已经确定了。而后安排在各个鱼塘钓鱼的时间。

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

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

【参考代码】

#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));//将fish数组的内容复制到f数组中 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/823305.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新手做抖音小店,想要快速起店,抓住这两点很关键

大家好&#xff0c;我是电商笨笨熊 抖音小店一定是近几年来爆火的电商项目&#xff0c;凭借着直播电商的方式在短短几年内迅速崛起&#xff0c;成为现在人尽皆知的电商项目。 然而在抖店里&#xff0c;不少进入的玩家都是新手&#xff0c;甚至都是盲目入店&#xff0c;没有任…

【Unity】Feature has expired(H0041)

【背景】 在一台很久不用的电脑上更新了个人License&#xff0c;并导入了云项目&#xff0c;打开时却报错&#xff1a; 【分析】 网上查说要删缓存等等&#xff0c;试过都不行。重装Hub也不行。 这种环境类型的原因很难从信息入手定位错误。 所以我自己检查项目上有什么问题…

MATLAB 浮点数 转化为 定点数

a fi(v,s,w,f) 一个 fi 对象&#xff0c;其值为 v&#xff0c;符号性为 s&#xff0c;字长为 w&#xff0c;小数长度为 f。 AD9361 a fi(0.707,1,12,11)

Qt实现XYModem协议(二)

1 概述 XMODEM协议是一种使用拨号调制解调器的个人计算机通信中广泛使用的异步文件运输协议。这种协议以128字节块的形式传输数据&#xff0c;并且每个块都使用一个校验和过程来进行错误检测。使用循环冗余校验的与XMODEM相应的一种协议称为XMODEM-CRC。还有一种是XMODEM-1K&am…

在列表b是在列表a的首位(末尾)增加了‘x‘元素,要求分别输出列表a(原列表)和列表b

在列表b是在列表a的首位增加了0元素&#xff0c;要求分别输出列表a&#xff08;原列表&#xff09;和列表b 1.创建副本的形式实现 如果你想要在列表 b 中增加元素 0&#xff0c;而不影响原始列表 a&#xff0c;你需要创建 b 的一个副本&#xff0c;而不是让 b 直接指向 a。这…

angular node版本问题导致运行出错时应该怎么处理

如下图所示&#xff1a; 处理方式如下&#xff1a; package.json中start跟build中添加&#xff1a;SET NODE_OPTIONS--openssl-legacy-provider即可

电气中的PT,VT,变压器区别

变压器&#xff08;Transformer&#xff09;和电压互感器&#xff08;Voltage Transformer, VT&#xff0c;也称作电压变压器或电位互感器&#xff09;虽然都是利用电磁感应原理来改变电压的设备&#xff0c;但它们在用途、设计和精度方面有明显的区别&#xff1a; 用途&#x…

还原matlab编辑器窗口和主窗口分开的问题

问题 matlab不知道早点的&#xff0c;点击运行后会弹出新的窗口&#xff0c;咋整都恢复不了 解决方案 首先&#xff0c;在编辑器窗口下&#xff0c;按ctrlshiftD&#xff0c;此时编辑器窗口和主窗口就合并了&#xff0c;问题解决。

TCP的一些功能详述

文章制作不易&#xff0c;望各位大佬多多点赞&#xff0c;球球各位啦&#xff01;&#xff01;&#xff01;&#xff01; 目录 1.TCP的简介 2.TCP协议中部分数据的理解 1.端口号 2.序列号 3.四位首部长度 4.6位保留位 5. 16位校验和 6.数据&#xff08;TCP的载荷&#…

CC254X 8051芯片手册介绍

1 8051CPU 8051是一种8位元的单芯片微控制器&#xff0c;属于MCS-51单芯片的一种&#xff0c;由英特尔(Intel)公司于1981年制造。Intel公司将MCS51的核心技术授权给了很多其它公司&#xff0c;所以有很多公司在做以8051为核心的单片机&#xff0c;如Atmel、飞利浦、深联华等公…

LeetCode 面试经典150题 209.长度最小的子数组

题目&#xff1a; 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 思路&#x…

mybatis的使用技巧7——mysql中in,exists,join的用法和区别

在实际项目开发中&#xff0c;sql查询中的连表查询和子查询用的是最多的&#xff0c;但是很多人对于in&#xff0c;exists&#xff0c;join的用法认识不足&#xff0c;随意运用&#xff0c;这种情况如果在大数据量查询时&#xff0c;会存在很大的隐患。 一.子查询&#xff08;…

【创建型模式】工厂方法模式

一、简单工厂模式 1.1 简单工厂模式概述 简单工厂模式又叫做静态工厂方法模式。 目的&#xff1a;定义一个用于创建对象的接口。实质&#xff1a;由一个工厂类根据传入的参数&#xff0c;动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。 简单工厂模式…

计算机组成原理和体系

常见的进制 {\quad} 二进制&#xff1a;0&#xff0c;1 {\quad} 八进制&#xff1a;0&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#xff0c;7 {\quad} 十进制&#xff1a;0&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;4&…

MT2046 巨大的错误

1.暴力代码 2/10 #include <bits/stdc.h> using namespace std; int n; int a[25]; int b[25]; int ans 0; bool err() {for (int i 1; i < n; i){if (a[i] b[i]){return false;}}return true; } int main() {cin >> n;for (int i 1; i < n; i){a[i] i…

FreeRTOS:day2

1.总结串口的发送和接收功能使用到的函数 串口发送函数 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout) UART_HandleTypeDef *huart&#xff1a;指定发送串口 const uint8_t *pData&#xff1a;要发…

【Mysql数据库进阶01】窗口函数

窗口函数 1 定义2 聚合窗口函数2.1 默认效果/累计效果2.2 前面两行当前一行2.3 前面一行当前一行后面一行 3 排名窗口函数3.1 排名函数3.1.1 排名函数案例 3.2 累积分布 4 取值窗口函数 1 定义 完整的窗口函数定义如下: window_function([expression]) over(partition byorde…

【nnUNetv2进阶】五、nnUNetv2 魔改网络-小试牛刀-加入注意力机制SpatialAttention

nnUNet是一个自适应的深度学习框架&#xff0c;专为医学图像分割任务设计。以下是关于nnUNet的详细解释和特点&#xff1a; 自适应框架&#xff1a;nnUNet能够根据具体的医学图像分割任务自动调整模型结构、训练参数等&#xff0c;从而避免了繁琐的手工调参过程。 自动化流程&a…

H3C交换机ACL部分规则不生效问题

问题描述 H3C交换机ACL部分规则不生效问题 H3C交换机配置ACL后&#xff0c;规则在100左右&#xff0c;约10个接口下调用后&#xff0c;单独 permit 4个指定源、目IP地址的流量。但是只有前2个生效&#xff0c;后边2个相同的配置不生效。 问题原因 ACL性能不够的问题 dis q…

刀具表面上的微结构

刀具表面微结构通常指在刀具表面对特定功能设计的微观纹理&#xff0c;这些纹理可以是沟槽、凹坑、凸起或任何其他形式的微观图案。这些微结构的设计和应用是为了改善刀具的切削性能&#xff0c;减少切削力和切削温度&#xff0c;提高切削效率和精度&#xff0c;同时降低切削液…