码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-08-19 12:48:30      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:har   style   getc   tput   input   close   const   整数   logs   

N个物品的体积为W1,W2......Wn(Wi为整数),与之相对应的价值为P1,P2......Pn(Pi为整数),从中选出K件物品(K <= N),使得单位体积的价值最大。
Input
第1行:包括2个数N, K(1 <= K <= N <= 50000)
第2 - N + 1行:每行2个数Wi, Pi(1 <= Wi, Pi <= 50000)
Output
输出单位体积的价值(用约分后的分数表示)。
Input示例
3 2
2 2
5 3
2 1
Output示例
3/4
————————————————————————————
第一眼看题目以为是贪心QAQ 后来发现不行
因为如果你现在已有的价值/体积是最佳
而现在有两个价值很小的物品 a b a价值比b大
但是a的体积远大于b的话 此时b肯定是更优的
所以正解应该是二分答案 判断是否合法就好辣
技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int M=50007;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int n,k;
int c[M],w[M];
LL sumx,sumy,ansx,ansy;
LL gcd(LL x,LL y){
    while(y){
        LL p=x%y;
        x=y;
        y=p;
    } 
    return x;
}
struct node{double v; int pos;}e[M];
bool cmp(node a,node b){return a.v-b.v>1e-6;}
bool check(double mid){
    for(int i=1;i<=n;i++) e[i].v=1.0*w[i]-1.0*c[i]*mid,e[i].pos=i; 
    sort(e+1,e+1+n,cmp);
    double sum=0; sumx=0; sumy=0;
    for(int i=1;i<=k;i++){
        sum+=e[i].v;
        sumx+=w[e[i].pos];
        sumy+=c[e[i].pos];
    }
    return sum>=0;
}
int main()
{
    n=read(); k=read();
    for(int i=1;i<=n;i++) c[i]=read(),w[i]=read();
    double l=0,r=50000;
    while(r-l>1e-6){
        double mid=(l+r)/2;
        if(check(mid)) l=mid,ansx=sumx,ansy=sumy;
        else r=mid;
    }
    LL d=gcd(ansx,ansy);
    printf("%lld/%lld\n",ansx/d,ansy/d);
    return 0;
}
View Code

 

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

标签:har   style   getc   tput   input   close   const   整数   logs   

原文地址:http://www.cnblogs.com/lyzuikeai/p/7395789.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!