【无标题】csp 202303-2 垦田计划

csp 202303-2 垦田计划

  • 70分优先队列
  • 100分优化思路

70分优先队列

目的:利用优先队列,每次利用资源使花费时间最长的项目天数-1,然后再放回优先队列。

想要将花费时间最长的项目放在堆顶

设置结构体

struct Node{
    long long cost;
    long long need;
    friend bool operator <(Node a,Node b){
        return a.cost<b.cost;
    }
}

然后主体部分的优先队列建立和入堆

	priority_queue<Node> q;
    for(int i=0;i<n;i++){
        Node node;
        cin>>node.cost>>node.need;
        q.push(node)
        limit+=(node.need*(node.cost-k));
    }

处理:如果当前资源足够,cost减去1之后再放回堆中

    while(true){
        Node now=q.top();
        if(m>now.need){
            q.pop();
            m-=now.need;
            now.cost-=1;
            q.push(now);
        }else{
            break;
        }
    }*

最后输出

cout<<q.top().cost<<endl

具体代码不再贴出

100分优化思路

例如,我们如果想要缩短最短时间至5天,所有当前花费时间为6天的都得一起缩短,也就说明这些cost=6的项目所需要的资源和need可以合并。
我们在之前的优先队列里,其实就是先将所有cost最大的都缩小到cost-1。重复这个过程直到最小。
这看上去是有顺序的,先处理cost,在cost-1,也就是说,我们可以不再用排序耗时的优先队列
(加快速度的关键)

这个时候我们就新纪录maxCost
从maxCost开始,m减去对应资源数,
然后那些cost=cost-1的项目们:

costAndALLNeed[i-1]+=costAndALLNeed[i];

这一行是核心的部分

#include 

using namespace std;

const int maxn=100010;
struct Node{
    long long cost;
    long long need;
    friend bool operator <(Node a,Node b){
        return a.cost<b.cost;
    }
};

long long maxCost;
//合并所有cost值相同的项目后对应的need资源数
long long costAndALLNeed[maxn];

int main() {
    long long n,m,k;
    cin>>n>>m>>k;

    long long limit=0;
    for(int i=0;i<n;i++){
        Node node;
        cin>>node.cost>>node.need;
        if(node.cost>maxCost) maxCost=node.cost;
        costAndALLNeed[node.cost]+=node.need;
        limit+=(node.need*(node.cost-k));
    }

    if(limit<=m){
        cout<<k<<endl;
        return 0;
    }

    for(int i=maxCost;i>0;i--){
        if(m>costAndALLNeed[i]){
            m = m - costAndALLNeed[i];
            costAndALLNeed[i-1]+=costAndALLNeed[i];
            maxCost--;
        }else{
            break;
        }
    }
    cout<<maxCost<<endl;
    return 0;
}

你可能感兴趣的:(csp,c++)