小郑的数学作业(蓝桥杯),贪心算法

目录

1.题目再现

2.问题理解

3.解题思路

4.AC代码

5.题目总结

5.1算法核心思想

5.1.1 贪心策略

5.1.2 优先队列(堆)的作用:

5.2 时间复杂度分析

5.3空间复杂度分析


1.题目再现

题目链接:4.小郑的数学作业 - 蓝桥云课

2.问题理解

  1. 学期天数:共有 N 天。

  2. 数学课:共有 M 节数学课,每节课在第 ai天进行,且每节课一定会布置作业。

  3. 交作业:共有 K 次交作业,每次交作业在第 bi天进行。每次交作业前,必须完成之前所有布置的作业。

  4. 幸福度:每天有一个幸福度 ci,如果这天不做作业,小郑会获得完整的 ci​ 幸福度;如果做作业,幸福度为 0。

  5. 作业完成规则:每天只能完成一份作业,且交作业是在早上,小郑不能在这天补写当天需要上交的作业。

我们的目标是找到一种策略,使得小郑在按时完成所有作业的前提下,整个学期的幸福度之和最大。

3.解题思路

为了最大化幸福度,我们需要在每次交作业前完成所有布置的作业,同时尽量减少做作业的天数,以保留更多的幸福度。

  1. 作业完成时机:每次交作业前,必须完成之前所有布置的作业。因此,我们需要在每次交作业前,选择一些天数来做作业。

  2. 选择做作业的天数:为了最大化幸福度,我们应该选择那些幸福度较低的天数来做作业,因为这样可以保留更多的高幸福度天数。

  3. 优先队列的使用:为了高效地选择幸福度最低的天数来做作业,我们可以使用一个最小堆(优先队列)来维护这些天数。

4.AC代码

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=510;
int n,m,k,c[N],sum,x;
bool a[N],b[N];
int main(){
  cin>>n>>m>>k;
  for(int i=1;i<=n;i++) cin>>c[i],sum+=c[i];
  for(int i=1;i<=m;i++) cin>>x,a[x]=1;
  for(int i=1;i<=k;i++) cin>>x,b[x]=1;
  priority_queue<int,vector<int>,greater<int>>q;
  int l,r;
  for(int i=1;i<=n;i++){
    if(b[i]){
      while(!q.empty()) q.pop();
      r=i-1;
      for(int j=r;j>=l;j--){
        q.push(c[j]);
        if(a[j]) sum-=q.top(),q.pop();
      }
      l=i;
    }
  }
  cout<<sum;
  return 0;
}
/*
其实b[i]就像是划分区间后的临界点,
初始区间的最左边l=1,
从遇到需要提交作业,就从他上一个点(r)向前找,
将数放进最小优先队列里面,
然后遇到a[i],就将最小数减去,更新l=i,
就这样不断地从r到l区间找a[i],就能求出来
*/

5.题目总结

5.1算法核心思想

5.1.1 贪心策略

每次交作业前,需要完成所有布置的作业。

为了最大化幸福度,我们应该尽量选择幸福度最低的天数来做作业,因为这样可以保留更多的高幸福度天数。

这种“每次选择局部最优解”的思想就是贪心算法的核心。

5.1.2 优先队列(堆)的作用

为了高效地找到当前区间内幸福度最低的天数,代码使用了最小堆(优先队列)

最小堆可以在 O(log⁡n)的时间内找到并移除最小的元素,非常适合用来动态维护当前区间内的最小幸福度。

5.2 时间复杂度分析

初始化

输入幸福度、布置作业和交作业的天数,时间复杂度为 O(N+M+K)。

遍历天数:

外层循环遍历 N 天,时间复杂度为 O(N)。

内层循环(处理区间 [l, r])在最坏情况下会遍历 N 天,时间复杂度为 O(N)。

每次操作优先队列的时间复杂度为 O(log⁡N)。

总时间复杂度

最坏情况下,总时间复杂度为 O(Nlog⁡N)。

5.3空间复杂度分析

优先队列

优先队列最多存储 N 个元素,空间复杂度为 O(N)。

其他数组

a[N]b[N]c[N] 的空间复杂度为 O(N)。

总空间复杂度:O(N)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值