您的位置:首页 > 其它

poj 3111 best(二分)

2017-01-09 20:10 309 查看

Problem Link

best

最大化平均值。

分析

需要找的是

∑kj=1vij∑kj=1wij最大的编号,我们可以二分一下答案∑kj=1vij∑kj=1wij≥x,使得x最大变一下形式我们可以得到

∑kj=1vij≥∑kj=1wij∗x即

∑vi−x∗wi≥0的最大的 x,这样对于每次答案就可以在O(nlgn)的时间内解决到了。

AC code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include <set>
#define fi first
#define se second
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const int maxn = 1e5+10;
int n,k;
struct Jewel{
double v,w;
int id;
};

Jewel a[maxn];
double x_cmp;
bool cmp(const Jewel& x,const Jewel& y){
return x.v-x_cmp*x.w>y.v-y.w*x_cmp;
}

bool condition(double x){
x_cmp = x;
sort(a,a+n,cmp);
double sum = 0;
for(int i=0 ; i<k ; ++i)sum+=a[i].v-x_cmp*a[i].w;
return sum>=0;
}
void solve(){
double left =0,right = 1e7+10;
while (right>left+1e-5) {
double mid = (right+left)/2;
if(condition(mid)){
left = mid;
}else right = mid;
}
//std::cout << right <<endl;
}

int main()
{
//freopen("in.txt","r",stdin);
while (cin>>n>>k) {
for(int i=0 ; i<n ; ++i)
{
scanf("%lf%lf",&a[i].v,&a[i].w );
a[i].id = i+1;
}
solve();
for(int i=0 ; i<k ; ++i)
printf("%d ",a[i].id);
std::cout << '\n';
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分