返回题解分享
讨论 / 题解分享/ 帖子详情

最大开支(编程题) - 题解

#include<iostream>
using namespace std;
#include<queue>
typedef long long ll;
ll fun(ll k,ll b,ll x)
{
    return k*x*x+b*x;
}
ll delty(ll k,ll b,ll x)
{
    return fun(k,b,x+1)-fun(k,b,x);
}
struct node
{
ll k,b,x;
bool operator<(const node& other)const 
{
return delty(k,b,x)<delty(other.k,other.b,other.x);
}
};
priority_queue<node> q;
int main()
{
    ll sum=0,n,m,k,b;
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>k>>b;
        q.push(node{k,b,0});
    }
    for(int i=1;i<=n;i++)
    {
        node p=q.top();
        q.pop();
        if(delty(p.k,p.b,p.x)<=0)
        {
break;
        }
        q.push(node{p.k, p.b, p.x + 1});
    }
while(q.size())
{
    node p=q.top();
    q.pop();
    sum+=fun(p.k,p.b,p.x);
}
cout<<sum;
return 0;
}
1 回复 0 转发 1 喜欢 0 阅读
回复 (1)
默认 最新
露米 2 天前
看到你分享的题解了,逻辑很清晰呢。利用优先队列来维护增量(delta)的思路很巧妙,把分配问题转化成了每一步的最优选择,贪心的策略在这里用得很自然。

在处理这类题目时,delta 函数的定义确实是核心。我也在想,在编写 operator< 的时候,如果数据规模再大一些,重复调用 delty 函数会不会对效率有一点点影响?或许可以尝试在结构体里直接维护当前的增量。

感谢你的分享,这对正在学习贪心算法的小伙伴很有参考价值。如果大家在尝试这段代码时有新的发现,也可以一起讨论 🙂
另外,我还注意到你在代码中特意处理了增量小于等于 0 时的 break,这个小细节能让程序在处理某些数据分布时更高效,真的很细心。

在写这道题的时候,你有考虑过如果输入数据中 $k$ 的值很大,会不会有其他的挑战吗?期待看到你的更多思考,加油~
0