zoukankan      html  css  js  c++  java
  • [二分][dp] Jzoj P3454 表白(love)

    Description

    鸡腿是CZYZ的著名DS,但是不想追妹子的DS不是好GFS,所以鸡腿想通过表白来达到他追到妹子的目的!虽然你对鸡腿很无语,但是故事的设定是你帮助鸡腿找到了妹子,所以现在你必须帮助鸡腿安排表白来实现故事的结局 ! 

    鸡腿想到了一个很高(sha)明(bi)的做法,那就是去找人来组成表白队伍来增强气势 !鸡腿有很多好基友来帮忙,鸡腿数了数一共有N个人。但是鸡腿觉得大家排成两队来比较好看,而且鸡腿经过计算,第一队N1个人,第二队N2个人是最佳的队伍。问题来了...有些好基友们虽然很好心但是可能造成不好的影响(形象猥琐),所以鸡腿就给每个人打了分。Q1i表示第i个好基友排到第一队里时的好影响,C1i表示第i个好基友排到第一队里时的不良影响,Q2i表示第i个好基友排到第二队里时的好影响,C2i表示第i个好基友排到第二队里时的不良影响。请给鸡腿一种安排使得Q的和与C的和的比值最大,给出最大值。 
     

    Input

    第一行给出三个整数N、N1、N2。 

    第2到N+1行,每行四个整数Q1,C1,Q2,C2。 

    Output

    一行输出一个小数d表示最优化比例是d(保留6位小数) 
     

    Sample Input

    5 2 2
    12 5 8 3
    9 4 9 4
    7 3 16 6
    11 5 7 5
    18 10 6 3

    Sample Output

    2.444444
     

    Data Constraint

    对于50%的数据0 < N1 + N2 ≤ N ≤ 50; 

    对于100%的数据0 < N1 + N2 ≤ N ≤ 500,1 ≤ Q1, Q2 ≤ 2000,1 ≤ C1, C2 ≤ 50。

    题解

    • 答案:ΣQ1[i]+ΣQ2[i]/ΣC1[i]+ΣC2[i]
    • 设当前比例x
    • 则有Σ(Q1[i]-C1[i]*x)+Σ(Q2[i]-C2[i]*x)>=0
    • 设a[i]为(Q1[i]-C1[i]*x)-(Q2[i]-C2[i]*x)
    • 这样的话我们只用判断 最后 两边 取的人 的a 的和>=0
    • 考虑二分x,恶心的精度!!!
    • 可以用DP来判断二分的合法性
    • 设f[i][j]、k[i][j]为前i个人取j个人的a的和
    • 先按a数组从大到小排序
    • 那么第一队列要选最优的肯定在前面,第二队肯定在后面
    • 第一队从前往后取,第二队从后往前取

    代码

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const double e=0.000000001;
     8 struct edge{ double x,y,v; }k[510];
     9 int Q1[510],Q2[510],C1[510],C2[510],n1,n2,n;
    10 double f[510][510],z[510][510],l,r,mid;
    11 bool cmp(edge x,edge y) { return x.v>y.v; }
    12 bool pd(double x)
    13 {
    14     for (int i=1;i<=n;i++)
    15     {
    16         k[i].x=Q1[i]-C1[i]*x;
    17         k[i].y=Q2[i]-C2[i]*x;
    18         k[i].v=k[i].x-k[i].y;
    19     }
    20     sort(k+1,k+n+1,cmp);
    21     memset(f,200,sizeof(f));
    22     memset(z,200,sizeof(z));
    23     f[0][0]=0;
    24     for (int i=1;i<=n;i++)
    25     {
    26         f[i][0]=0;
    27         for (int j=1;j<=min(n1,i);j++) f[i][j]=max(f[i-1][j],f[i-1][j-1]+k[i].x);
    28     }    
    29     z[0][0]=0;
    30     for (int i=n;i>=1;i--)
    31     {
    32         z[n-i+1][0]=0;
    33         for (int j=1;j<=min(n2,n-i+1);j++) z[n-i+1][j]=max(z[n-i][j],z[n-i][j-1]+k[i].y);
    34     }
    35     for (int i=n1;i<=n-n2;i++) if (f[i][n1]+z[n-i][n2]>=0) return true; 
    36     return false;
    37 }
    38 int main()
    39 {
    40     //freopen("love.in","r",stdin);
    41     //freopen("love.out","w",stdout);
    42     scanf("%d%d%d",&n,&n1,&n2);
    43     for (int i=1;i<=n;i++) scanf("%d%d%d%d",&Q1[i],&C1[i],&Q2[i],&C2[i]);
    44     l=0.01; r=2000;
    45     while (l+e<r)
    46     {
    47         mid=(l+r)/2;
    48         if (pd(mid)) l=mid; else r=mid-e;
    49     }
    50     printf("%.6f",l);
    51     return 0;
    52 }
  • 相关阅读:
    MySql模糊查询like通配符使用详细介绍
    使用powershell批量添加Qt的文件(生成pro)
    宏定义的教训
    使用powershell批量添加Keil和IAR的头文件路径
    python和数据科学(Anaconda)
    CDCE913产生任意频率
    QT中检索设定目录下所有指定文件的方法
    QT中将ASCII转换为对应数值的方法
    STM8如何使用自带的bootloader
    QT中使用函数指针
  • 原文地址:https://www.cnblogs.com/Comfortable/p/9274007.html
Copyright © 2011-2022 走看看