CCF- CSP 202303-2垦田计划 【多种方法】满分题解

CCF- CSP 202303-2垦田计划 【多种方法】满分题解

题目链接:CCF- CSP 202303-2垦田计划

70分思路:

  • 从基础耗时最长的区域进行筛选,每次基础耗时减少一天
  • 该方法以m作为参考对象,对m进行减的操作(m的数据范围达到1e9,导致超时)
  • 采用优先队列作为存储结构,同时存储tc

代码如下:

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int n,m,k;
typedef pair<int,int>PII;//采用pair同时存储t和c
priority_queue<PII,vector<PII> > heap;//采用优先队列
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
        int t,c;
        cin>>t>>c;
        heap.push({t,c});//压入队列
    }
    while(m>0)
    {
        PII t = heap.top();//取出当前基础耗时最大的
        heap.pop();//记得删除最大点
        //如果最大值不满足条件
        if(t.first<=k)
        {
            heap.push(t);
            break;
        }
        m -=t.second;//每次只缩减一天
        t.first -= 1;
        heap.push(t);
    }
    cout<<heap.top().first<<endl;//输出基础耗时最大的值
    return 0;
}

100分思路1:

  • 在70分思路的基础上,发现超时的原因:m的数据范围达到了1e9,造成超时
  • 可能改进的方法:按照基础耗时的大小进行筛选,一次循环缩减大量资源。而不是像70分代码思路:一次只减少一天的资源量
  • 从基础耗时最小值k,最大值mx进行筛选,一次操作可以使m的值大量减少
  • 采用二分算法,对所有可能的耗时进行搜索(范围为k~mx),找到最短耗时

代码如下:

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int n,m,k;
int t[N],c[N];
int mx;//记录最大天数
//判断当前耗时天数x能否满足需求
bool jude(int x)
{
    int sum = 0;//记录资源总和
    for(int i=1;i<=n;i++)
    {
        if(t[i]<x)continue;//基础耗时小于x,不需要考虑资源消耗
        sum+=(t[i]-x)*c[i];//sum的值进行改变
        if(sum>m)return false;//如果资源总和大于m,不满足条件
    }
    return true;
}
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>t[i]>>c[i];
        mx = max(mx,t[i]);
    }
    int l=k,r=mx;//二分:左边起点为l,右边为mx
    while(l<=r)
    {
        int mid = (l+r)>>1;
        if(jude(mid)) r=mid-1;//满足条件,往小范围搜索
        else l = mid+1;
    }
    cout<<l<<endl;
    return 0;
}

100分思路2:

  • 70分思路是对每一个区域单独处理,仔细分析后,发现可以对同一基础耗时的区域同时处理
  • 单独开一个数组sa用来记录同一基础耗时的区域所需资源总数
  • mxk依次处理,每次使得最大基础耗时的区域同时减少一天

代码如下:

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int n,m,k;
int t[N],c[N];
int sa[N];//记录同一基础耗时缩减一天所需要的总资源
int mx;//记录基础耗时的最大值
int main()
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>t[i]>>c[i];
        sa[t[i]]+=c[i];//记录同一基础耗时缩减一天所需要的总资源
        mx = max(mx,t[i]);
    }
    int ans = mx;//记录结果
    for(int i=mx;i>=k;i--)
    {
        if(sa[ans]>m)break;
        m-=sa[ans];//同一基础耗时的同时减少一天
        sa[ans-1]+=sa[ans];//下一天的需要加上上一天的资源总数
        //ans的最小值为k
        if(ans>k)
        {
            ans--;
        }
    }
    cout<<ans<<endl;
    return 0;
}
  • 26
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值