[贪心] 二元组最小值最大

本文探讨了在给定N个二元组的情况下,如何通过贪心算法结合动态更新策略,选取K个二元组使ai的最小值与bi的最小值之和达到最大。介绍了使用小顶堆维护可能的最优解,并通过动态更新实现正确解的算法过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 CCPC省赛的时候和队友讨论了多值同时贪心怎么最优, 没整出来, 今天就碰到这种题了。。。

私以为贪心不是特别容易凭空构造出一种严谨/正确的贪心方案

我这种铁牌选手只能多看多学吧,没什么别的方法


题目:

给定N个二元组(a1,b1),(a2,b2),…,(aN,bN),请你从中选出恰好K个,使得ai的最小值与bi的最小值之和最大。

请输出ai的最小值与bi的最小值之和


 

解法:

先贪心一个值, 然后动态贪心第二个值, 类似二分答案

按a 或 b值从大到小排序

然后从前先后遍历, 维护一个答案小顶堆(里面是另一个值)

易证:若堆体积大于k 弹出的堆顶必然不是最优解,

当体积等于k时 堆顶必然是当前1 - now中 b值的范围最优解,

arr[now].fst 也是最优解 (开始已排序固定)

最后动态更新答案既为正确值


代码


const int MAXN = 1e6 + 10;
 
struct node
{
    ll fst, lst;
}arr[MAXN];
 
bool cmp(node a, node b)
{
    return a.fst > b.fst;
}

priority_queue <ll, vector<ll>, greater<ll> > PQ;
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);     cout.tie(0);
    //freopen("D://test.in", "r", stdin);
    //freopen("D://test.out", "w", stdout);
 
    ll n, k;
 
    cin >> n >> k;
 
    for(int i = 0; i < n; ++i)
    {
        cin >> arr[i].fst >> arr[i].lst;
    }
 
    sort(arr, arr + n, cmp);
    
    ll ans = -INF;

    for(int i = 0; i < n; ++i)
    {
        PQ.push(arr[i].lst);

        if(PQ.size() > k)
            PQ.pop();

        if(PQ.size() == k)
        {
            ans = max(ans, PQ.top() + arr[i].fst);
        }
    }
 
    cout << ans << '\n';
 
    return 0;
}


 

走班排课使用贪心算法的LINGO代码如下,代码中包含了详细的注释: ``` SETS: I: 课程集合; J: 班级集合; DATA: a(I,J): 每个班级能够在每个时间段上课的课程数; b(I): 每个课程需要的时间段数; c(J): 每个班级需要的总时间段数; VARIABLES: x(I,J): 课程 i 是否安排在班级 j 中; EQUATIONS: 班级时间段约束(j in J): sum(i in I, b(i)*x(i,j)) = c(j); 老师能够教授的课程约束(i in I): sum(j in J, x(i,j)) <= a(i,j); MODEL: Z := @SUM(i in I, j in J, x(i,j)); // 定义目标函数,求最小值 ! 以下为贪心算法 FOR(j, 1, @CARD(J), 1, FOR(i, 1, @CARD(I), 1, IF(sum(k in J, x(i,k)) < a(i,j) AND sum(k in I, b(k)*x(k,j)) < c(j) AND x(i,j) = 0, x(i,j) = 1; BREAK; // 找到一个可行的课程安排,跳出当前循环 ); ); ); SOLVE; ``` 在代码中,我们首先定义了个集合:课程集合和班级集合,以及三个数据:每个班级能够在每个时间段上课的课程数、每个课程需要的时间段数、每个班级需要的总时间段数。然后我们定义了一个二元变量 x(i,j) 表示课程 i 是否安排在班级 j 中。 在约束方程中,我们分别定义了班级时间段约束和老师能够教授的课程约束。其中,班级时间段约束保证每个班级的总时间段数等于需要的总时间段数,老师能够教授的课程约束保证每个老师只能教授他能够教授的课程。 在模型中,我们定义了一个目标函数 Z,它是所有 x(i,j) 的和。我们要求 Z 的最小值,即最小化冲突课程的数量。然后,我们使用贪心算法来求解这个问题。具体来说,我们依次遍历班级和课程,对于每个班级和课程,我们判断是否存在一个可行的课程安排方案(即班级能够在这个时间段上课,老师能够教授这门课程,且这个课程没有被安排在其他班级中),如果存在,则安排这门课程在这个班级上课,并跳出当前循环。 最后,我们使用 SOLVE 命令来求解这个模型,得到一个合理的走班排课方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值