51nod 1257 背包问题 V3

本文介绍了一种解决0-1分数规划问题的方法,并通过一个具体的数学模型详细阐述了如何利用二分查找来确定最优解的过程。文章还提供了一个完整的C++实现代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目
题解
01分数规划

0-1 分数规划
     t1 * x1 + t2 * x2 + ... + tn * xn
 r = ---------------------------------
     c1 * x1 + c2 * x2 + ... + cn * xn
给定t[1..n], c[1..n], 求x[1..n]使得sigma(xi)=k且r最大(小). 
为了让r最大, 先设计子问题z(r) = (t1 * x1 + .. + tn * xn) - r * (c1 * x1 + .. + cn * xn);
假设r的最优值为R. 则有:
z(r) < 0 当且仅当 r > R;
z(r) = 0 当且仅当 r = R;
z(r) > 0 当且仅当 r < R;
于是可二分求R.
#include<bits/stdc++.h>
using namespace std;
typedef double D;
const int N=50002;
const D eps=1e-6;
struct node{
    int p,w;
    D c;
}a[N];
int n,k,i,G,x,y,xx,yy;
D l,r,mid;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x=0,fl=1;char ch=gc();
    for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
    for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
    return x*fl;
}
bool cmp(node a,node b){
    return a.c>b.c;
}
bool check(int &x,int &y,D p){
    for (int i=0;i<n;i++) a[i].c=a[i].p-p*a[i].w;
    nth_element(a,a+k-1,a+n,cmp);
    x=0;y=0;D z=0;
    for (int i=0;i<k;i++){
        x+=a[i].p;y+=a[i].w;
        z+=a[i].c;
    }
    return z>=0;
}
int main(){
    n=read();k=read();
    for (i=0;i<n;i++) a[i].w=read(),a[i].p=read();
    l=0;r=2e9;
    while (r-l>eps){
        mid=(l+r)/2;
        if (check(x,y,mid)) l=mid,xx=x,yy=y;
        else r=mid;
    }
    G=__gcd(xx,yy);
    xx/=G;yy/=G;
    printf("%d/%d",xx,yy);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值