贪心--CF529B

题目大意:有n 个人,每个人有两个属性wi; hi,n 个人的价值和为wi的和*max(hi)
现在你可以让不超过⌊n2⌋ 个人的wi 与hi 值互换,求能得到的最小价值和

solution:
枚举最后方案中最大的h,设为maxh
若某个人i 的wi 与hi 均大于maxh 则此方案不可行
若某个人恰有一个属性大于maxh 则可确定他是否换属性
剩下的人按wi - hi 从大到小排序后贪心选择
O(n log n + n2)

这个题···提交无数次wa
细节还是有的,而且注意枚举的时候不能按h枚举
要从1到w和h中最大的数依次枚举
因为这个wa了好几遍0.0

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 1005
#define LL long long
using namespace std;
int n,num,sumw,mh,q[maxn],tot,mx;
LL ans;

inline int rd(){
  int x=0,f=1; char c=' ';
  while(c<'0' || c>'9') {if(c=='-') f=-1;c=getchar();}
  while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
  return x*f;
}

struct qwq{
  int w,h;
}a[maxn];

bool cmp(int x,int y) {return x>y;}

LL check(int maxh){
  int cnt=0,tmp=sumw;
  tot=0; memset(q,0,sizeof q);//这个一开始还忘记加了···
  for(int i=1;i<=n;i++){
    if(a[i].w>maxh && a[i].h>maxh) return -1;
    if(a[i].w<=maxh && a[i].h>maxh) tmp=tmp-a[i].w+a[i].h,cnt++;
    if(cnt>num) return -1;
    else if(a[i].w<=maxh && a[i].h<=maxh) q[++tot]=a[i].w-a[i].h;
  }
  sort(q+1,q+tot+1,cmp);//记得要按w-h排序
  for(int i=1;i<=min(tot,num-cnt);i++){
    if(q[i]>0) tmp-=q[i];
  }
  return 1LL*tmp*maxh;
}

int main(){
  n=rd(); num=n/2;
  for(int i=1;i<=n;i++){
    a[i].w=rd(),a[i].h=rd();
    sumw+=a[i].w; mh=max(mh,a[i].h); mx=max(mx,max(mh,a[i].w));
  }//mdzz还得算一下mx
  ans=1LL*sumw*mh;
  for(int i=1;i<=mx;i++){//一开始是枚举所有的h,但应该从1到mx枚举
    LL t=check(i);
    if(t>=0) ans=min(ans,t);
  }
  printf("%lld\n",ans);
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值