P1842 [USACO05NOV] 奶牛玩杂技 【贪心题解】

文章介绍了如何运用贪心算法解决一道关于奶牛玩杂技的问题,涉及体重力气分配对压扁指数的影响,通过证明两种情况下的压扁指数关系,得出体重力气较大的牛在下方能减小总压扁指数的结论,并给出了C++代码实现。
摘要由CSDN通过智能技术生成


前言

这题主要考查贪心算法,那我们就要想一想怎么去得到“体重力气”之和与每头牛位置的关系,确定了这两者的关系就可以得到最优解。

看完提示的同学可以先再想一想如何解出这道题


一、题目

P1842 [USACO05NOV] 奶牛玩杂技

在这里插入图片描述


二、解题过程

1.证明过程

假设现在有两头牛x,y(x.w+x.s>y.w+y.s)
第一种情况:x在y的上面(w为x上面的牛的重量)
x.w-y.s>y.w-x.s
因为y.w>=0
所以x.w-y.s>-x.s => w+x.w-y.s>w-x.s
所以总的压扁指数为: w+x.w-y.s

第二种情况:y在x的上面(w为y上面的牛的重量)
x.w-y.s>y.w-x.s
因为x.w>=0
所以y.w-x.s>-y.s => w+y.w-x.s>w-y.s
所以总的压扁指数为:w+y.w-x.s

总的压扁指数
1、y在下面时:w+x.w-y.s
2、x在下面时:w+y.w-x.s

因为w+x.w-y.s>w+y.w-x.s => x.w+x.s>y.w+y.s
所以体重力气之和大的牛在下面能够使总的压扁指数最小。


2.代码

#include<bits/stdc++.h>
using namespace std;
#define li inline
#define gc getchar
#define pc putchar
#define wr(n) write(n,false),pc('\n')
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define loop(n) for(int i=0;i<n;++i)
#define loops(n) for(int i=0;i<=n;++i)
#define LL long long
#define int LL
const int N=1e5+10;
//每头牛的体重和力气
struct Node 
{
    int w,s;
}node[N];
//快读模板
int read(){
    int x=0,f=0;
    char ch=gc();
    while('0'>ch||ch>'9')f|=ch=='-',ch=gc();
    while('0'<=ch&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=gc();
    return f?-x:x;
}
//快写模板
void write(int x){
    if(x<0)pc('-'),x=-x;
    if(x>9)write(x/10);
    pc(x%10+'0');
    return;
}
//排序函数,从小到大
bool cmp(Node& a,Node& b){
    return a.w+a.s<b.w+b.s;
}
signed main(){
    int n;
    n = read();
    for(int i=0;i<n;++i){ 
        node[i].w = read(); 
        node[i].s = read(); 
    }
    sort(node,node+n,cmp);
    //ans取很小的负数是因为总的压扁指数有可能是负数 
    //ans总的压扁指数,weight总体重
    int ans=-0x3f3f3f,weight=0;
    for(int i=0;i<n;++i){
    	//因为要取每头牛的最大压扁指数为总的压扁指数
        ans=max(ans,weight-node[i].s);
        //体重力气从小到大,小体重力气在上面,大体重力气在下面
        //先遍历小体重力气就是从上往下遍历
        //遍历到i时,就用1-(i-1)个牛的体重减去第i头牛的力气
        weight+=node[i].w;
    }
    cout<<ans<<"\n"; 
    return 0;
}

如果觉得对你有所帮助的话,请点个免费的赞吧!

  • 13
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值