欢迎光临
我们一直在努力

邻接交换和反悔贪心

基础

贪心算法 是一种在每一步决策时都采取当前状态下的最优选择,并通过一系列局部最优解来推导全局最优解的算法范式。

适用条件

  • 最优子结构(Optimal Substructure) 一个问题具有最优子结构,是指问题的最优解包含其子问题的最优解

  • 贪心选择性质(Greedy Choice Property) 全局最优解可以通过一系列局部最优(贪心)选择得到。不存在一个非贪心选择,能够比贪心选择产生更优的全局解。

  • 局限性

    贪心算法并不总是有效。当问题具有以下特征时,贪心策略通常会失效:

  • 局部最优不导向全局最优(如 0-1 背包问题)。
  • 决策间存在相互制约(如旅行商问题)。
  • 最优解需要牺牲当前利益以换取未来更大收益(如数字金字塔)。
  • 反悔贪心

    反悔贪心先不管数据是否最优,先加入,后遇到更优数据则替换最劣数据(根据题意判断),通常需要用 优先队列(堆) 存储数据。

    例题:P4053 建筑抢修

    贪心目标

    尽量多抢修建筑。

    分析

    显然,要抢修尽量多的建筑,需要优先修修理时间短、报废时间少的,晚修修理时间长、报废时间晚的。

    使用反悔贪心思想,按报废时间从小到大排序,取消修理时间长的。

    遍历时修理建筑

    i

    i

    i,将修理时间加入大根堆。如果修理(结束)时间晚于建筑(

    i

    i

    i)报废时间,则从大根堆取堆顶(时间最长的),取出后代表其取消修理。这样子保证了修理建筑数量相同,操作后的修理时间一定

    <

    =

    <=

    <=操作钱的修理时间。

    #include<bits/stdc++.h>
    using namespace std;
    #define t1 second
    #define t2 first
    #define int long long
    const int N = 150010;
    priority_queue<int> q;
    int n,ans,tot;
    pair<int,int> p[N];
    //tot已过时间,ans已修理建筑数量
    signed main(){
    scanf("%lld",&n);
    for(int i = 1;i<=n;i++) scanf("%lld%lld",&p[i].t1,&p[i].t2);//注意t2对应first,按t2从小到大排序
    sort(p+1,p+n+1);
    for(int i = 1;i<=n;i++){
    tot+=p[i].t1;
    q.push(p[i].t1);
    ans++;
    if(tot>p[i].t2){
    ans;
    tot-= q.top();
    q.pop();
    }
    }
    printf("%lld",ans);
    return 0;
    }


    邻接交换

    这通常解决需要一个最优排列顺序的问题

  • 考虑两个元素 A 和 B
  • 假设当前顺序是… A B …交换后为… B A …
  • 计算交换和不交换的优劣,决定是否交换
  • 例题1:P1080 国王游戏

    贪心目标

    安排一个排队顺序,使获得奖赏最大的大臣所获得的奖赏尽量小。

    分析

    在排序中计算

    i

    i

    i,

    j

    j

    j 排列先后顺序。

    s

    s

    s 为排在该大臣前面的所有人的左手上的数的乘积(不包括该大臣)。

    c

    i

    c_i

    ci 为大臣

    i

    i

    i 所获得的奖赏。

    a

    i

    a_i

    ai,

    b

    i

    b_i

    bi 分别为编号为

    i

    i

    i 的大臣的左右手上的数。

    i

    i

    i

    j

    j

    j 后时

    c

    i

    1

    =

    s

    b

    i

    c_{i_1} = \\left\\lfloor \\frac{s}{b_i} \\right\\rfloor

    ci1=bis

    c

    j

    1

    =

    s

    ×

    a

    i

    b

    j

    c_{j_1} = \\left\\lfloor \\frac{s \\times a_i}{b_j} \\right\\rfloor

    cj1=bjs×ai

    j

    j

    j

    i

    i

    i 后时

    c

    j

    2

    =

    s

    b

    j

    c_{j_2} = \\left\\lfloor \\frac{s}{b_j} \\right\\rfloor

    cj2=bjs

    i

    2

    =

    s

    ×

    a

    j

    b

    j

    _{i_2} = \\left\\lfloor \\frac{s \\times a_j}{b_j} \\right\\rfloor

    i2=bjs×aj

    由于需要奖赏最大的大臣的奖赏尽量小,顺序是否是

    i

    i

    i

    j

    j

    j 后由以下不等式是否成立决定

    max

    (

    c

    i

    1

    ,

    c

    j

    1

    )

    <

    max

    (

    c

    i

    2

    ,

    c

    j

    2

    )

    \\max(c_{i_1},c_{j_1}) < \\max(c_{i_2},c_{j_2})

    max(ci1,cj1)<max(ci2,cj2)

    max

    (

    s

    b

    i

    ,

    s

    ×

    a

    i

    b

    j

    )

    <

    max

    (

    s

    ×

    a

    j

    b

    i

    ,

    s

    b

    j

    )

    \\max(\\left\\lfloor \\frac{s}{b_i} \\right\\rfloor,\\left\\lfloor \\frac{s \\times a_i}{b_j} \\right\\rfloor) < \\max(\\left\\lfloor \\frac{s \\times a_j}{b_i} \\right\\rfloor,\\left\\lfloor \\frac{s}{b_j} \\right\\rfloor)

    max(bis,bjs×ai)<max(bis×aj,bjs) 约掉

    s

    s

    s

    max

    (

    1

    b

    i

    ,

    a

    i

    b

    j

    )

    <

    max

    (

    a

    j

    b

    i

    ,

    1

    b

    j

    )

    \\max(\\left\\lfloor \\frac{1}{b_i} \\right\\rfloor,\\left\\lfloor \\frac{a_i}{b_j} \\right\\rfloor) < \\max(\\left\\lfloor \\frac{a_j}{b_i} \\right\\rfloor,\\left\\lfloor \\frac{1}{b_j} \\right\\rfloor)

    max(bi1,bjai)<max(biaj,bj1) 同乘

    b

    i

    ×

    b

    j

    b_i \\times b_j

    bi×bj

    max

    (

    b

    j

    ,

    a

    i

    ×

    b

    i

    )

    <

    max

    (

    a

    j

    ×

    b

    j

    ,

    b

    i

    )

    \\max(b_j,a_i \\times b_i) < \\max(a_j \\times b_j,b_i)

    max(bj,ai×bi)<max(aj×bj,bi) 显然,在

    a

    i

    ,

    a

    j

    ,

    b

    i

    ,

    b

    j

    1

    a_i,a_j,b_i,b_j \\ge 1

    ai,aj,bi,bj1 时,必然有

    b

    j

    a

    j

    ×

    b

    j

    b_j \\le a_j \\times b_j

    bjaj×bj

    b

    i

    a

    i

    ]

    ×

    b

    i

    b_i \\le a_i] \\times b_i

    biai]×bi 则舍去

    b

    i

    b_i

    bi,

    b

    j

    b_j

    bj 两项,原式得

    a

    i

    ×

    b

    i

    <

    a

    j

    ×

    b

    j

    a_i \\times b_i < a_j \\times b_j

    ai×bi<aj×bj

    得出当

    a

    i

    ×

    b

    j

    <

    a

    j

    ×

    b

    j

    a_i \\times b_j < a_j \\times b_j

    ai×bj<aj×bj 时,

    i

    i

    i,

    j

    j

    j 不交换

    输入数据并排序,后用模拟法得出答案。但是题目涉及大数累乘,答案最大可达

    10

    4000

    10^{4000}

    104000 。即便是 __int128 类型也远远无法处理,因此需要高精度。示例代码为

    60

    p

    t

    s

    60pts

    60pts,无高精度处理。

    60分代码

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N = 1010;
    int n,s,ans,t;
    struct node{
    int a,b;
    }q[N];
    bool cmp(node a,node b){
    return a.a*a.b<b.a*b.b;
    }
    signed main(){
    scanf("%lld%lld%lld",&n,&s,&t);
    for(int i = 1;i<=n;i++){
    scanf("%lld%lld",&q[i].a,&q[i].b);
    }
    sort(q+1,q+n+1,cmp);
    for(int i = 1;i<=n;i++){
    ans = max(s/q[i].b,ans);
    s *= q[i].a;
    }
    printf("%lld",ans);
    return 0;
    }

    例题2:P2123 皇后游戏

    题外话,皇后游戏是邻接交换贪心的巅峰之作,还是非常吃脑子的。

    贪心目标

    安排一个排队顺序,使获得奖金最大的大臣所获得的奖赏尽量小。

    分析

    c

    i

    c_i

    ci

    i

    i

    i 大臣获得的奖金。

    s

    i

    s_i

    si

    k

    =

    1

    n

    a

    j

    \\sum_{k = 1}^n a_j

    k=1naj

    a

    i

    a_i

    ai,

    b

    i

    b_i

    bi 分别为编号为

    i

    i

    i 的大臣的左右手上的数。

    由题得知

    c

    i

    =

    max

    (

    c

    i

    1

    ,

    s

    i

    1

    +

    a

    i

    )

    +

    b

    i

    c_i = \\max(c_{i-1},s_{i-1} + a_i) + b_i

    ci=max(ci1,si1+ai)+bi

    s

    i

    =

    s

    i

    1

    +

    a

    i

    s_i = s_{i-1}+a_i

    si=si1+ai

    i

    i

    i

    j

    j

    j

    c

    i

    1

    =

    max

    (

    c

    i

    1

    ,

    s

    i

    1

    +

    a

    i

    )

    +

    b

    i

    c_{i_1} = \\max(c_{i-1},s_{i-1}+a_i)+b_i

    ci1=max(ci1,si1+ai)+bi

    c

    j

    1

    =

    max

    (

    max

    (

    c

    i

    1

    ,

    s

    i

    1

    +

    a

    i

    )

    +

    b

    i

    ,

    s

    i

    1

    +

    a

    i

    +

    a

    j

    )

    +

    b

    j

    c_{j_1} = \\max(\\max(c_{i-1},s_{i-1}+a_i)+b_i,s_{i-1}+a_i+a_j)+b_j

    cj1=max(max(ci1,si1+ai)+bi,si1+ai+aj)+bj

    c

    i

    1

    c_{i_1}

    ci1

    c

    j

    1

    c_{j_1}

    cj1 最大值

    k

    1

    =

    max

    {

    c

    i

    1

    +

    b

    i

    ,

    s

    i

    1

    +

    a

    i

    +

    b

    i

    +

    b

    j

    ,

    c

    i

    1

    +

    b

    i

    +

    b

    j

    ,

    s

    i

    1

    +

    a

    i

    +

    a

    j

    +

    b

    j

    }

    k_1 = \\max\\{ c_{i-1}+b_i, s_{i-1}+a_i+b_i+b_j, c_{i-1}+b_i+b_j, s_{i-1}+a_i+a_j+b_j \\}

    k1=max{ci1+bi,si1+ai+bi+bj,ci1+bi+bj,si1+ai+aj+bj} 由以上皆为正整数,

    c

    i

    1

    +

    b

    i

    <

    c

    i

    1

    +

    b

    i

    +

    b

    j

    c_{i-1}+b_i < c_{i-1}+b_i+b_j

    ci1+bi<ci1+bi+bj

    k

    1

    =

    max

    {

    s

    i

    1

    +

    a

    i

    +

    b

    i

    +

    b

    j

    ,

    c

    i

    1

    +

    b

    i

    +

    b

    j

    ,

    s

    i

    1

    +

    a

    i

    +

    a

    j

    +

    b

    j

    }

    k_1 = \\max\\{ s_{i-1}+a_i+b_i+b_j, c_{i-1}+b_i+b_j, s_{i-1}+a_i+a_j+b_j \\}

    k1=max{si1+ai+bi+bj,ci1+bi+bj,si1+ai+aj+bj}

    j

    j

    j

    i

    i

    i

    c

    j

    1

    =

    max

    (

    c

    j

    1

    ,

    s

    j

    1

    +

    a

    j

    )

    +

    b

    j

    c_{j_1} = \\max(c_{j-1},s_{j-1}+a_j)+b_j

    cj1=max(cj1,sj1+aj)+bj

    c

    i

    1

    =

    max

    (

    max

    (

    c

    j

    1

    ,

    s

    j

    1

    +

    a

    j

    )

    +

    b

    j

    ,

    s

    j

    1

    +

    a

    j

    +

    a

    i

    )

    +

    b

    i

    c_{i_1} = \\max(\\max(c_{j-1},s_{j-1}+a_j)+b_j,s_{j-1}+a_j+a_i)+b_i

    ci1=max(max(cj1,sj1+aj)+bj,sj1+aj+ai)+bi

    c

    i

    2

    c_{i_2}

    ci2

    c

    j

    2

    c_{j_2}

    cj2 最大值

    k

    2

    =

    max

    {

    c

    j

    1

    +

    b

    j

    ,

    s

    j

    1

    +

    a

    j

    +

    b

    j

    +

    b

    i

    ,

    c

    j

    1

    +

    b

    j

    +

    b

    i

    ,

    s

    j

    1

    +

    a

    j

    +

    a

    i

    +

    b

    i

    }

    k_2 = \\max\\{ c_{j-1}+b_j, s_{j-1}+a_j+b_j+b_i, c_{j-1}+b_j+b_i, s_{j-1}+a_j+a_i+b_i \\}

    k2=max{cj1+bj,sj1+aj+bj+bi,cj1+bj+bi,sj1+aj+ai+bi} 由以上皆为正整数,

    c

    j

    1

    +

    b

    j

    <

    c

    j

    1

    +

    b

    j

    +

    b

    i

    c_{j-1}+b_j < c_{j-1}+b_j+b_i

    cj1+bj<cj1+bj+bi

    k

    2

    =

    max

    {

    s

    j

    1

    +

    a

    j

    +

    b

    j

    +

    b

    i

    ,

    c

    j

    1

    +

    b

    j

    +

    b

    i

    ,

    s

    j

    1

    +

    a

    j

    +

    a

    i

    +

    b

    i

    }

    k_2 = \\max\\{ s_{j-1}+a_j+b_j+b_i, c_{j-1}+b_j+b_i, s_{j-1}+a_j+a_i+b_i \\}

    k2=max{sj1+aj+bj+bi,cj1+bj+bi,sj1+aj+ai+bi}

    k

    1

    <

    k

    2

    k_1<k_2

    k1<k2

    max

    {

    s

    i

    1

    +

    a

    i

    +

    b

    i

    +

    b

    j

    ,

    c

    i

    1

    +

    b

    i

    +

    b

    j

    ,

    s

    i

    1

    +

    a

    i

    +

    a

    j

    +

    b

    j

    }

    <

    max

    {

    s

    j

    1

    +

    a

    j

    +

    b

    j

    +

    b

    i

    ,

    c

    j

    1

    +

    b

    j

    +

    b

    i

    ,

    s

    j

    1

    +

    a

    j

    +

    a

    i

    +

    b

    i

    }

    \\max\\{ s_{i-1}+a_i+b_i+b_j, c_{i-1}+b_i+b_j, s_{i-1}+a_i+a_j+b_j \\} < \\max\\{ s_{j-1}+a_j+b_j+b_i, c_{j-1}+b_j+b_i, s_{j-1}+a_j+a_i+b_i \\}

    max{si1+ai+bi+bj,ci1+bi+bj,si1+ai+aj+bj}<max{sj1+aj+bj+bi,cj1+bj+bi,sj1+aj+ai+bi} 消去公共项

    c

    i

    1

    +

    b

    i

    +

    b

    j

    c_{i-1}+b_i+b_j

    ci1+bi+bj

    max

    {

    s

    i

    1

    +

    a

    i

    +

    b

    i

    +

    b

    j

    ,

    s

    i

    1

    +

    a

    i

    +

    a

    j

    +

    b

    j

    }

    <

    max

    {

    s

    j

    1

    +

    a

    j

    +

    b

    j

    +

    b

    i

    ,

    s

    j

    1

    +

    a

    j

    +

    a

    i

    +

    b

    i

    }

    \\max\\{ s_{i-1}+a_i+b_i+b_j, s_{i-1}+a_i+a_j+b_j \\} < \\max\\{ s_{j-1}+a_j+b_j+b_i, s_{j-1}+a_j+a_i+b_i \\}

    max{si1+ai+bi+bj,si1+ai+aj+bj}<max{sj1+aj+bj+bi,sj1+aj+ai+bi} 提取

    s

    i

    1

    s_{i-1}

    si1

    s

    j

    1

    s_{j-1}

    sj1,从逻辑上我们知道

    s

    i

    1

    s_{i-1}

    si1

    s

    j

    1

    s_{j-1}

    sj1 意义一样,消去

    max

    {

    a

    i

    +

    b

    i

    +

    b

    j

    ,

    a

    i

    +

    a

    j

    +

    b

    j

    }

    <

    max

    {

    a

    j

    +

    b

    j

    +

    b

    i

    ,

    a

    j

    +

    a

    i

    +

    b

    i

    }

    \\max\\{ a_i+b_i+b_j, a_i+a_j+b_j \\} < \\max\\{ a_j+b_j+b_i, a_j+a_i+b_i \\}

    max{ai+bi+bj,ai+aj+bj}<max{aj+bj+bi,aj+ai+bi} 分别提

    a

    i

    +

    b

    j

    a_i+b_j

    ai+bj

    a

    j

    +

    b

    i

    a_j+b_i

    aj+bi

    max

    {

    b

    i

    ,

    a

    j

    }

    +

    a

    i

    +

    b

    j

    <

    max

    {

    b

    j

    ,

    a

    i

    }

    +

    a

    j

    +

    b

    i

    \\max\\{b_i,a_j\\}+a_i+b_j < \\max\\{b_j,a_i\\}+a_j+b_i

    max{bi,aj}+ai+bj<max{bj,ai}+aj+bi 移项

    max

    {

    b

    i

    ,

    a

    j

    }

    a

    j

    b

    i

    <

    max

    {

    b

    j

    ,

    a

    i

    }

    a

    i

    b

    j

    \\max\\{b_i,a_j\\}-a_j-b_i < \\max\\{b_j,a_i\\}-a_i-b_j

    max{bi,aj}ajbi<max{bj,ai}aibj

    min

    (

    b

    i

    ,

    a

    j

    )

    <

    min

    (

    b

    j

    ,

    a

    i

    )

    -\\min(b_i,a_j) < -\\min(b_j,a_i)

    min(bi,aj)<min(bj,ai)

    min

    (

    b

    i

    ,

    a

    j

    )

    >

    min

    (

    b

    j

    ,

    a

    i

    )

    \\min(b_i,a_j) > \\min(b_j,a_i)

    min(bi,aj)>min(bj,ai) 由于含

    min

    \\min

    min 是偏序,要转换为全序,所以要转换一下。

    bool cmp(pe x,pe y){
    int xt = (x.a<=x.b)?0:1,yt = (y.a<=y.b)?0:1;
    if(xt!=yt) return xt<yt;
    if(xt==0) return x.a<y.a;
    else return x.b>y.b;
    }


    题外话

    原本是要把剩下几个贪心都写了的,但是关电脑忘保存了,直接哭晕在厕所

    赞(0)
    未经允许不得转载:171主机测评 » 邻接交换和反悔贪心
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址