题意:求n个东西里取k个,使它们平均值最大,输出这个k个东西序号。
思路:这题数据很大,开始我没注意二分的细节,一直TLE,顿时感觉这题有毒。
改了两个地方就AC,一个是 把排序的定义方式cmp写成结构体里对<的重载
bool cmp(node a,node b)
{
return a.b>=b.b;
}
改成:
struct node
{
double b;int t;
bool operator<(const struct node&a)const//重载运算符
{
return b>a.b;
}
}a[100000+10];
还有吧二分退出的条件改成精度控制1e-6,开始我写的都是for(int i=0;i<100;i++){}
for(int i=0;i<100;i++){
double mid=(l+r)*0.5;
if(check(mid)) l=mid;
else r=mid;
}
改成:
while(r-l>=1e-6){
double mid=(l+r)*0.5;
if(check(mid)) l=mid;
else r=mid;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int ans[100000+10],v[100000+10],w[100000+10],n,k;
struct node
{
double b;int t;
bool operator<(const struct node&a)const//重载运算符
{
return b>a.b;
}
}a[100000+10];
bool check(double x)
{
for(int i=1;i<=n;i++) a[i].b=v[i]-x*w[i],a[i].t=i;
sort(a+1,a+1+n);
double sum=0;
for(int i=1;i<=k;i++) sum+=a[i].b,ans[i]=a[i].t;
return sum>=0;
}
int main()
{
while(~scanf("%d%d",&n,&k)){
for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&w[i]);
double l=0,r=100001;
while(r-l>=1e-6){
double mid=(l+r)*0.5;
if(check(mid)) l=mid;
else r=mid;
}
int ok=1;
for(int i=1;i<=k;i++){
if(ok) ok=0;
else printf(" ");
printf("%d",ans[i]);
}
printf("\n");
}
}
后来看讨论,这题还可以用一个数学知识:牛顿迭代解决。
以下转自 大牛的博客:
牛顿迭代:
http://blog.youkuaiyun.com/yew1eb/article/details/38728357
牛顿迭代解法:
http://blog.youkuaiyun.com/yew1eb/article/details/38730447