【POJ 3045】Cow Acrobats(贪心)

博客探讨了如何用贪心算法解决POJ 3045 - Cow Acrobats的问题。通过将奶牛按照重量与强壮度之和排序,可以达到最小化任何一头奶牛的最大崩溃风险的目标。贪心证明显示这种策略的正确性。

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

题面:Cow Acrobats
题目大意

相当于有 n n n 头奶牛在叠罗汉。每头牛都有两个特质,一个是重量 w w w,一个是强壮度 s s s
每头牛都有一个崩溃风险,该风险等于在她上面的所有奶牛的总重量减去她本身的强壮度。所以每头牛都要找到合适自己的位置。
求:确定所有奶牛的位置,从而使任何奶牛中的最大风险最小。

思路

芜湖~~先贪心试一下。
将每头牛按照 w + s w+s w+s 从小到大排序,这样就得到正确的答案啦哈哈哈哈哈哈。

贪心证明:

设最优解为 r e a l _ a n s real\_ans real_ans,自己方案的解为 a n s ans ans

要证: a n s = r e a l _ a n s ans=real\_ans ans=real_ans
只需证:

  1. a n s ≤ r e a l _ a n s ans\leq real\_ans ansreal_ans
  2. a n s ≥ r e a l _ a n s ans\ge real\_ans ansreal_ans

证明如下:

1、由题意可知,必然有 r e a l _ a n s ≤ a n s real\_ans\leq ans real_ansans

2、假设最优解不是按我们的算法来做的,则至少有一对牛是交换了位置的。已知第 k k k 头牛的特征为 ( w k , s k ) (w_k,s_k) (wk,sk),第 k + 1 k+1 k+1 头牛的特征为 ( w k + 1 , s k + 1 ) (w_{k+1},s_{k+1}) (wk+1,sk+1),且她们的风险分别为, r i s k , r i s k + 1 ris_k,ris_{k+1} risk,risk+1,则:

位置交换前交换后
k k k r i s k = ∑ i = 1 k − 1 w i − s k ris_k=\sum_{i=1}^{k-1}w_i-s_k risk=i=1k1wisk r i s k = ∑ i = 1 k − 1 w i + w k + 1 − s k ris_k=\sum_{i=1}^{k-1}w_i+w_{k+1}-s_k risk=i=1k1wi+wk+1sk
k+1 r i s k + 1 = ∑ i = 1 k w i − s k + 1 ris_{k+1}=\sum_{i=1}^kw_i-s_{k+1} risk+1=i=1kwisk+1 r i s k + 1 = ∑ i = 1 k − 1 w i − s k + 1 ris_{k+1}=\sum_{i=1}^{k-1}w_i-s_{k+1} risk+1=i=1k1wisk+1

同时减去 ∑ i = 1 k − 1 w i \sum_{i=1}^{k-1}w_i i=1k1wi 可得:

位置交换前交换后
k k k − s k -s_k sk w k + 1 − s k w_{k+1}-s_k wk+1sk
k + 1 k+1 k+1 w k − s k + 1 w_k-s_{k+1} wksk+1 − s k + 1 -s_{k+1} sk+1

由于 s , w ≥ 1 s,w\ge1 s,w1,所以有:
w k + 1 − s k > − s k w_{k+1}-s_k>-s_k wk+1sk>sk, w k − s k + 1 > − s k + 1 w_{k}-s_{k+1}>-s_{k+1} wksk+1>sk+1

所以,我们只要比较 w k + 1 − s k w_{k+1}-s_k wk+1sk w k − s k + 1 w_k-s_{k+1} wksk+1 的大小关系即可。
两边同时加上 s k + s k + 1 s_k+s_{k+1} sk+sk+1 得:
w k + 1 + s k + 1 w_{k+1}+s_{k+1} wk+1+sk+1 w k + s k w_k+s_k wk+sk
因为我们的贪心算法是按照 w + s w+s w+s 从小到大排序的。
所以, w k + 1 + s k + 1 ≥ w k + s k w_{k+1}+s_{k+1}\ge w_k+s_k wk+1+sk+1wk+sk
所以,交换前的解要小于交换后的解,即 a n s ≤ r e a l _ a n s ans\leq real\_ans ansreal_ans

综上, a n s = r e a l _ a n s ans=real\_ans ans=real_ans。证毕。

代码
#include <bits/stdc++.h>
#define sc scanf
#define pf printf
using namespace std;
const int N = 5e4 + 10;
const int INF = 0x3f3f3f3f;

struct Node
{
    int w, s;
    bool operator<(const Node &x) const
    {
        return w + s < x.w + x.s;
    }
}cow[N];

int main()
{
    int n;
    sc("%d", &n);
    for(int i = 0; i < n; i++) {
        int w, s;
        sc("%d %d", &w, &s);
        cow[i] = {w, s};
    }
    sort(cow, cow + n);
    
    int ans = -INF, sum = 0;
    for(int i = 0; i < n; i++) {
        ans = max(ans, sum - cow[i].s);
        sum += cow[i].w;
    }
    pf("%d\n", ans);
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值