AcWing 1262. 鱼塘钓鱼(每日一题)

2024-03-09 21:04
文章标签 每日 acwing 钓鱼 鱼塘 1262

本文主要是介绍AcWing 1262. 鱼塘钓鱼(每日一题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

暴力枚举法:

贪心:


原题链接:1262. 鱼塘钓鱼 - AcWing题库

有 N个鱼塘排成一排,每个鱼塘中有一定数量的鱼,例如:N=5 时,如下表:

鱼塘编号12345
第1分钟能钓到的鱼的数量(1..1000)101420169
每钓鱼1分钟钓鱼数的减少量(1..100)24653
当前鱼塘到下一个相邻鱼塘需要的时间(单位:分钟)3544

即:在第 1 个鱼塘中钓鱼第 1 分钟内可钓到 10 条鱼,第 2分钟内只能钓到 8 条鱼,……,第 5 分钟以后再也钓不到鱼了。

从第 1 个鱼塘到第 2 个鱼塘需要 3 分钟,从第 2 个鱼塘到第 3 个鱼塘需要 5 分钟,……

给出一个截止时间 T,设计一个钓鱼方案,从第 1 个鱼塘出发,希望能钓到最多的鱼。

假设能钓到鱼的数量仅和已钓鱼的次数有关,且每次钓鱼的时间都是整数分钟。

输入格式

共 5 行,分别表示:

第 1 行为 N;

第 2 行为第1 分钟各个鱼塘能钓到的鱼的数量,每个数据之间用一空格隔开;

第 3 行为每过 1 分钟各个鱼塘钓鱼数的减少量,每个数据之间用一空格隔开;

第 4 行为当前鱼塘到下一个相邻鱼塘需要的时间;

第 5 行为截止时间 T。

输出格式

一个整数(不超过2^31−1),表示你的方案能钓到的最多的鱼。

数据范围

1≤N≤100
1≤T≤1000

输入样例:

5
10 14 20 16 9
2 4 6 5 3
3 5 4 4
14

输出样例:

76

暴力枚举法:

由于此题数据量很小可以进行暴力枚举,当前鱼塘可以掉一会时间,当到达转移时间时,可以花费c[i]去转移到下一个鱼塘,获得更多的鱼,dp[i][j]=dp[i+1][k]+dp[i][j-k-c[i]];

#include<iostream>
#include<string>
using namespace std;
int n,t;
bool flag=0;
int a[105],a1[105],b[105],c[105];
int dp[105][1005];
int main(){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;i++)cin>>c[i];cin>>t;for(int i=1;i<=n;i++){for(int j=1;j<=t;j++){dp[i][j]=dp[i][j-1]+a[i];a[i]=max(a[i]-b[i],0);}}for(int i=n-1;i>=1;i--){//逆序枚举鱼塘个数,因为下面要处理第i+1个鱼塘,i+1要先于i更新for(int j=t;j>=c[i];j--){//j为总时间,花费最少c[i],用来走到下一个鱼塘int maxx=dp[i][j];for(int k=0;k<=j-c[i];k++){//可以给i+1个分配k个时间,那么剩下j-k-c[i]为第i个鱼塘的时间maxx=max(maxx,dp[i+1][k]+dp[i][j-k-c[i]]);}dp[i][j]=maxx;}}cout<<dp[1][t]<<endl;return 0;
}

贪心:

这个题我们可以把一个鱼塘可以钓的鱼数全部列举出来,从中选取k大的数即为答案,这个k又是啥,我们的总时间T可以分为路程时间+钓鱼时间,我们枚举一下最多到哪一个终点,此时路程时间便可以知道,那么钓鱼的时间=总时间T-路程时间,注释附在代码上。

#include<iostream>
#include<cstring>
using namespace std;
const int N=105;
int n,t,res;
int a[N],b[N],c[N],s[N];
//a表示第 1分钟各个鱼塘能钓到的鱼的数量,b表示鱼减少的数量
//c表示到达各个鱼塘时间,s表示在第i个鱼塘钓的时间
int get(int k){//在第k个鱼塘可以钓的鱼数return max(0,a[k]-b[k]*s[k]);//初始a[k],每次减少b[k],钓了s[k]分钟//所以此时可以在第k个鱼塘钓a[k]-b[k]*s[k]个,但不能小于0
}
//多路归并,每一次寻找可以钓的最大鱼数
int work(int n,int t){//n表示最多移动到第n个鱼塘,t表示钓鱼的时间int res=0;memset(s,0,sizeof(s));//初始都为0for(int i=1;i<=t;i++){//枚举每一分钟int m=1;//记录最大下标for(int j=2;j<=n;j++){//枚举1-n的鱼塘数if(get(m)<get(j)){//第j个鱼塘所获得的鱼数小于第m个鱼塘所获得的鱼数,则更新下标m=j;}}res+=get(m);s[m]++;//在第m个上钓鱼要花费时间}return res;
}
int main(){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=2;i<=n;i++){cin>>c[i];c[i]+=c[i-1];//前缀和求花费移动鱼塘的时间}cin>>t;for(int i=1;i<=n;i++){//枚举第一个鱼塘到第i个鱼塘最大获得多少鱼res=max(res,work(i,t-c[i]));//t-c[i]表示总时间减去移动花费的时间,剩下为钓鱼的时间}cout<<res<<endl;return 0;
}

这样时间复杂度会大大优化,如果数据量再大一点,暴力枚举就会寄了

此题贪心思路按照y总的讲解写的,里面涉及了多路归并等算法,此题还有更多解法,不再一一介绍了,文章尚有不足,欢迎大佬们指正。

这篇关于AcWing 1262. 鱼塘钓鱼(每日一题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/791938

相关文章

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

每日一练7:简写单词(含链接)

1.链接 简写单词_牛客题霸_牛客网 2.题目 3.代码1(错误经验) #include <iostream>#include <string>using namespace std;int main() {string s;string ret;int count = 0;while(cin >> s)for(auto a : s){if(count == 0){if( a <=

【每日刷题】Day113

【每日刷题】Day113 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 91. 解码方法 - 力扣(LeetCode) 2. LCR 098. 不同路径 - 力扣(LeetCode) 3. 63. 不同路径 II - 力扣(LeetCode) 1. 91. 解码方法 - 力扣(LeetCode) //思路:动态规划。 cl

【AcWing】851. 求最短路

spfa算法其实是对贝尔曼福特算法做一个优化。 贝尔曼福特算法会遍历所有边来更新,但是每一次迭代的话我不一定每条边都会更新,SPFA是对这个做优化。 如果说dist[b]在当前这次迭代想变小的话,那么一定是dist[a]变小了,只有a变小了,a的后继(b)才会变小。 用宽搜来做优化,用一个队列,队列里边存的就是所有变小了的结点(队列里存的是待更新的点)。 基本思路就是我更新过谁,我再拿

力扣 739. 每日温度【经典单调栈题目】

1. 题目 理解题意: 1.1. 给一个温度集合, 要返回一个对应长度的结果集合, 这个结果集合里面的元素 i 是 当前 i 位置的元素的下一个更高温度的元素的位置和当前 i 位置的距离之差, 若是当前元素不存在下一个更高温度的元素, 则这个位置用0代替; 2. 思路 本题用单调栈来求解;单调栈就适用于来求当前元素左边或者右边第一个比当前元素大或者小的元素;【单调栈:让栈中的元素保持单调

每日一题——第八十一题

打印如下图案: #include<stdio.h>int main() {int i, j;char ch = 'A';for (i = 1; i < 5; i++, ch++){for (j = 0; j < 5 - i; j++){printf(" ");//控制空格输出}for (j = 1; j < 2 * i; j++)//条件j < 2 * i{printf("%c", ch

每日一题,力扣leetcode Hot100之238.除自身以外数组的乘积

乍一看这个题很简单,但是不能用除法,并且在O(N)时间复杂度完成或许有点难度。 考虑到不能用除法,如果我们要计算输出结果位置i的值,我们就要获取这个位置左边的乘积和右边的乘积,那么我新设立两个数组L和R。 对于L来说,由于表达的是位置i左边的数的乘积,那么L[0]=1,因为第一个数字左边没数那么为了不影响乘积初始值就设置为1,那么L[1]=L[0]*nums[0],那么L[i]=L[i-1

英语每日一段 195

Promising economic indicators won’t instantly reverse the lingering impact of hard times for millions of families, workplace culture expert Jessica Kriegel said. “Perception and reality are sometimes

GitHub每日最火火火项目(9.7)

项目名称:polarsource / polar 项目介绍:polar 是一个开源的项目,它是 Lemon Squeezy 的替代方案,具有更优惠的价格。该项目旨在让开发者能够凭借自己的热情进行编码并获得报酬。通过使用 polar,开发者可以更轻松地实现自己的创意和项目,并从中获得收益。 项目地址:https://github.com/polarsource/polar项目名称:psf / bla