zoukankan      html  css  js  c++  java
  • 【BZOJ 4819】 4819: [Sdoi2017]新生舞会 (0-1分数规划、二分+KM)

    4819: [Sdoi2017]新生舞会

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 601  Solved: 313

    Description

    学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴。有n个男生和n个女生参加舞会
    买一个男生和一个女生一起跳舞,互为舞伴。Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 
    a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度。Cathy还需要考虑两个人一起跳舞是否方便,
    比如身高体重差别会不会太大,计算得出 b[i][j],表示第i个男生和第j个女生一起跳舞时的不协调程度。当然,
    还需要考虑很多其他问题。Cathy想先用一个程序通过a[i][j]和b[i][j]求出一种方案,再手动对方案进行微调。C
    athy找到你,希望你帮她写那个程序。一个方案中有n对舞伴,假设没对舞伴的喜悦程度分别是a'1,a'2,...,a'n,
    假设每对舞伴的不协调程度分别是b'1,b'2,...,b'n。令
    C=(a'1+a'2+...+a'n)/(b'1+b'2+...+b'n),Cathy希望C值最大。

    Input

    第一行一个整数n。
    接下来n行,每行n个整数,第i行第j个数表示a[i][j]。
    接下来n行,每行n个整数,第i行第j个数表示b[i][j]。
    1<=n<=100,1<=a[i][j],b[i][j]<=10^4

    Output

    一行一个数,表示C的最大值。四舍五入保留6位小数,选手输出的小数需要与标准输出相等

    Sample Input

    3
    19 17 16
    25 24 23
    35 36 31
    9 5 6
    3 4 2
    7 8 9

    Sample Output

    5.357143

    HINT

    Source

    【分析】

      好吧费用流竟然给过。。。

      但是我打KM。。。算练一练吧。。。还是打错了两个地方【要记住下次不要错了啊!!!

      就是经典的0-1分数规划

      二分答案mid

      则$sum a[i][j]-mid*b[i][j]>=0$,这个用KM做最大费用判断是否大于等于0即可。

      然后精度要弄小一点才不会被卡,弄到了1e-10,然后狂T是因为INF不够大,晕。。。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<cmath>
     7 using namespace std;
     8 #define Maxn 110
     9 const double eps=1e-10;
    10 const double INF=1e12;
    11 
    12 double a[Maxn][Maxn],b[Maxn][Maxn];
    13 
    14 int visx[Maxn],visy[Maxn],match[Maxn];
    15 double slack[Maxn],lx[Maxn],ly[Maxn];
    16 int n;
    17 
    18 bool ffind(double mid,int x,int nt)
    19 {
    20     visx[x]=nt;
    21     for(int y=1;y<=n;y++) if(visy[y]!=nt)
    22     {
    23         if(fabs(lx[x]+ly[y]-(a[x][y]-mid*b[x][y]))<eps)
    24         {
    25             visy[y]=nt;
    26             if(!match[y]||ffind(mid,match[y],nt))
    27             {
    28                 match[y]=x;
    29                 return 1;
    30             }
    31         }
    32         else slack[y]=min(slack[y],lx[x]+ly[y]-(a[x][y]-mid*b[x][y]));
    33     }
    34     return 0;
    35 }
    36 
    37 bool check(double mid)
    38 {
    39     for(int i=1;i<=n;i++) match[i]=0;
    40     for(int i=1;i<=n;i++)
    41     {
    42         visx[i]=visy[i]=0;
    43         lx[i]=-INF;ly[i]=0;
    44         for(int j=1;j<=n;j++) lx[i]=max(lx[i],a[i][j]-mid*b[i][j]);
    45     }int nt=0;
    46     for(int i=1;i<=n;i++)
    47     {
    48         for(int j=1;j<=n;j++) slack[j]=INF;
    49         while(1)
    50         {
    51             nt++;
    52             if(ffind(mid,i,nt)) break;
    53             double delta=INF;
    54             for(int j=1;j<=n;j++) if(visy[j]!=nt) delta=min(delta,slack[j]);
    55             for(int j=1;j<=n;j++)
    56             {
    57                 if(visx[j]==nt) lx[j]-=delta;
    58                 if(visy[j]==nt) ly[j]+=delta;
    59                 else if(fabs(INF-slack[j])<eps) slack[j]-=delta;
    60             }
    61         }
    62     }
    63     double ans=0;
    64     for(int i=1;i<=n;i++) ans+=lx[i]+ly[i];
    65     return ans>=0;
    66 }
    67 
    68 int main()
    69 {
    70     double l=0,r=0;
    71     scanf("%d",&n);
    72     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lf",&a[i][j]),r+=a[i][j];
    73     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lf",&b[i][j]);
    74     while(r-l>eps)
    75     {
    76         double mid=(l+r)/2;
    77         if(check(mid)) l=mid;
    78         else r=mid;
    79     }
    80     printf("%.6lf
    ",l);
    81     return 0;
    82 }
    View Code

    2017-04-28 13:21:57

  • 相关阅读:
    免费的mysql客户端管理工具
    vue配置反向代理
    composer下载地址
    mysql多个字段模糊查询是否包含某个词
    Laravel 7 中文文档
    datatable显示文字改为中文
    MongoDB
    node 与 Ajax 的等待响应
    关于 <!DOCTYPE html> 对移动端和PC端的影响
    Vue中 scoped属性
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6781183.html
Copyright © 2011-2022 走看看