贪心(二)

哈夫曼树

合并果子

在这里插入图片描述

每次合并堆中权值最小两个点,直到得到完整的哈夫曼树,证明略

#include<iostream>
#include<algorithm>
#include<queue>

using namespace std;

int n;

int main(){
    
    cin>>n;
    
    priority_queue<int,vector<int>,greater<int>> heap;
    
    for(int i=0;i<n;i++){
        
        int w;
        
        cin>>w;
        
        heap.push(w);
    }
    
    int res=0;
    
    while(heap.size()>1){
        
        int a=heap.top();
        
        heap.pop();
        
        int b=heap.top();
        
        heap.pop();
        
        heap.push(a+b);
        
        res+=a+b;
    }
    
    cout<<res;
}

排序不等式

排队打水

在这里插入图片描述

短进程优先,现将所有等待时间从小到大排序即是等待时间最优解

#include<iostream>
#include<algorithm>

using namespace std;

const int N=1e5+10;

int s[N],a[N];

int main(){
    
    int n;
    
    cin>>n;
    
    long long  res=0;
    
    for(int i=1;i<=n;i++)cin>>a[i];
    
    sort(a+1,a+n+1);
    
    for(int i=1;i<=n;i++){
        
        s[i]=s[i-1]+a[i];
        
        res+=s[i-1];
    }
    
    cout<<res;
}

绝对值不等式

货仓选址

在这里插入图片描述

假设坐标为x1,x2...xn-1,xn
(n为偶数时,将其两两分组),得到distance=abs(xn-x1)+abs(xn-1-x2).....+abs(x (n+1)/2 -x(n-1)/2 ).
显然可以得出,当x区在中间位置时,可得总和最小值,n为奇数时去得xn/2即可

#include<iostream>
#include<algorithm>

using namespace std;

const int N=1e5+10;

int a[N];

int main(){
    
    int n;
    
    cin>>n;
    
    int res=0;
    
    for(int i=0;i<n;i++)cin>>a[i];
    
    sort(a,a+n);                     //首先将各点按照坐标从大到小存放
    
    for(int i=0;i<n;i++)res+=abs(a[i]-a[n/2]);
    
    cout<<res;
}

推公式

耍杂技的牛

在这里插入图片描述

假设存在一序列N1,N2.......Ni1,Ni+1,....
现考量第i头牛和第i+1头牛之间风险系数的关系

  • 当前两头牛的风险值分别为   N i = W 1 + W 2 + . . . W i − 1 − S i \ N_{i}=W_1+W_2+...W_{i-1}-S_i  Ni=W1+W2+...Wi1Si
      N i + 1 = W 1 + W 2 + . . . W i − 1 + W i − S i + 1 \ N_{i+1}=W_1+W_2+...W_{i-1}+W_{i}-S_{i+1}  Ni+1=W1+W2+...Wi1+WiSi+1
  • 调换两头牛位置之后风险值分别为   N i = W 1 + W 2 + . . . W i − 1 + W i + 1 − S i \ N_{i}=W_1+W_2+...W_{i-1}+W_{i+1}-S_{i}  Ni=W1+W2+...Wi1+Wi+1Si
      N i + 1 = W 1 + W 2 + . . . W i − 1 − S i + 1 \ N_{i+1}=W_1+W_2+...W_{i-1}-S_{i+1}  Ni+1=W1+W2+...Wi1Si+1
  • 去掉公共部分得到交换前后的风险值分别为
  • 交换前:   N i = − S i \ N_{i}=-S_i  Ni=Si,   N i + 1 = W i − S i + 1 \ N_{i+1}=W_{i}-S_{i+1}  Ni+1=WiSi+1
  • 交换后:   N i = W i + 1 − S i \ N_{i}=W_{i+1}-S_{i}  Ni=Wi+1Si
      N i + 1 = − S i + 1 \ N_{i+1}=-S_{i+1}  Ni+1=Si+1
  • 显而易见,交换前后的风险值最大值显然应该在交换前的Ni+1和交换后的Ni中选取
  • 倘若满足Ni+1>Ni,即得到   W i + S i > W i + 1 + S i + 1 \ W_i+S_i>W_{i+1}+S_{i+1}  Wi+Si>Wi+1+Si+1
    交换之后可以降低最大风险值大小
  • 由此得出,只要将体重和强壮之和小的牛排在上面即可
#include<iostream>
#include<algorithm>

using namespace std;

const int N=50010;

typedef pair<int,int> PII;

PII cows[N];

int n;

int main(){
    
    cin>>n;
    
    for(int i=0;i<n;i++){
        
        int w,s;
        
        cin>>w>>s;
        
        cows[i]={w+s,w};
    }
    
    sort(cows,cows+n);              //按照w+s从小到大排序
    
    int sum=0,res=-2e9;             //初始化重量和,以及风险最大值
    
    for(int i=0;i<n;i++){
        
        int s=cows[i].first-cows[i].second,w=cows[i].second;
        
        res=max(res,sum-s);
        
        sum+=w;
    }
    
    cout<<res;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值