51nod 1257 背包问题 V3(分数规划)

  显然是分数规划...主要是不会求分数的形式,看了题解发现自己好傻逼QAQ

  还是二分L值算出d[]降序选K个,顺便记录选择时候的p之和与w之和就可以输出分数形式了...

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
#define ll long long 
using namespace std;
const int maxn=500010,inf=1e9;
struct poi{double sum;int pos;}d[maxn];
int n,K,ansx,ansy,x,y;
int p[maxn],w[maxn];
double mid;
void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
    k*=f;
}
bool cmp(poi a,poi b){return a.sum-b.sum>1e-6;}
bool check()
{
    for(int i=1;i<=n;i++)d[i].sum=1.0*p[i]-1.0*mid*w[i],d[i].pos=i;
    sort(d+1,d+1+n,cmp);
    double sum=0.0;x=y=0;
    for(int i=1;i<=K;i++)
    {
        x+=p[d[i].pos];y+=w[d[i].pos];
        sum+=d[i].sum;
    }    
    if(sum>=0)return 1;
    return 0;
}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
int main()
{
    read(n);read(K);
    for(int i=1;i<=n;i++)read(w[i]),read(p[i]);
    double l=0,r=50000;
    while(r-l>1e-6)
    {
        mid=(l+r)/2;
        if(check())l=mid,ansx=x,ansy=y;
        else r=mid;
    }
    ll d=gcd(ansx,ansy);
    printf("%lld/%lld",ansx/d,ansy/d);
    return 0;
}
View Code

 

原文地址:https://www.cnblogs.com/Sakits/p/7383660.html