zoukankan      html  css  js  c++  java
  • [51nod] 1257 背包问题 V3

    1257 背包问题 V3

    基准时间限制:3 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
     
    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
    Analysis分析
    qwq与01分数规划打了场遭遇战
    贪心 w/v 被证明是错误的,因为我写完全WA了
    而且样例就直接卡掉了这个贪心策略 
    那么我们可以一步一步来,首先记答案为 : 
     
    那么经过简单的数学变换我们得到:

    然后有:

    即:       

    那么我们二分这个R,使等式的结果无限接近 0 即可

    Emmmmm

    (其实没推清楚)

    Code代码

     1 #include<stdio.h>
     2 #include<math.h>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 int n,k;
     8 long long ansv,answ;
     9 
    10 double eps = 0.000000001;
    11 
    12 struct data{
    13     long long w,v;
    14     double vrw;
    15 }arr[1000000];
    16 
    17 bool cmp(const data &a,const data &b){ return a.vrw > b.vrw; }
    18 
    19 bool check(long long &sumv,long long &sumw,double line){
    20     for(int i = 1;i <= n;i++)
    21         arr[i].vrw = 1.0*arr[i].v-line*arr[i].w;
    22     
    23     sort(arr+1,arr+1+n,cmp);
    24     
    25     double tmp = 0;
    26     sumv = 0,sumw = 0;
    27     for(int i = 1;i <= k;i++)
    28         sumv += arr[i].v,
    29         sumw += arr[i].w,
    30         tmp += arr[i].vrw;
    31     
    32     return tmp >= 0;
    33 }
    34 
    35 long long gcd(long long a,long long b){
    36     if(a < b) swap(a,b);
    37     return !b?a:gcd(b,a%b);
    38 }
    39 
    40 int main(){
    41     
    42     scanf("%d%d",&n,&k);
    43     
    44     for(int i = 1;i <= n;i++)
    45         scanf("%lld%lld",&arr[i].w,&arr[i].v);
    46     
    47     double L = 0,R = 1000000;
    48     long long sumv,sumw;
    49     while(R-L > eps){
    50 //        printf("%.8lf %.8lf
    ",L,R);
    51         double mid = (L+R)/2;
    52         if(check(sumv,sumw,mid)) ansv = sumv, answ = sumw, L = mid;
    53         else R = mid;
    54     }
    55     
    56     long long d = gcd(ansv,answ);
    57     printf("%lld/%lld",ansv/d,answ/d);
    58     
    59     return 0;
    60 }
    注意,当分母为一的时候也,,,= =
  • 相关阅读:
    【JZOJ6409】困难的图论
    学习LCT小结
    jzoj5432. 【NOIP2017提高A组集训10.28】三元组
    jzoj6367. 【NOIP2019模拟2019.9.25】工厂(factory)
    jzoj6366. 【NOIP2019模拟2019.9.25】化学(chem)
    jzoj5433. 【NOIP2017提高A组集训10.28】图
    学习拓展中国剩余定理小结
    jzoj6300. Count
    jzoj3736. 【NOI2014模拟7.11】数学题
    jzoj6276. 【noip提高组模拟1】树
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7723055.html
Copyright © 2011-2022 走看看