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

Posted Sakits

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

 

以上是关于51nod 1257 背包问题 V3(分数规划)的主要内容,如果未能解决你的问题,请参考以下文章

[51nod] 1257 背包问题 V3

51nod 1257 背包问题 V3(这不是背包问题是二分)

1257 背包问题 V3——分数规划

01分数规划

51nod 1101 换零钱 完全背包的变型 动态规划

用动态规划求解分数背包问题