[Sdoi2017]新生舞会

[Sdoi2017]新生舞会

http://www.lydsy.com/JudgeOnline/problem.php?id=4819

Time Limit: 10 Sec  Memory Limit: 128 MB
[Submit][Status][Discuss]

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

01分数规划+费用流

ans=Σ a/ Σ b

Σ a=Σ(b*ans)

a1-b1*ans+a2-b2*ans+a3-b3*ans……=0

二分ans

以ai-bi*ans 为费用跑最大费用流

若费用>=0,则调整下界

否则,调整上界

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#define eps 1e-8
#define N 111
#define M 11111
using namespace std;
int n,src,decc;
double ans;
int a[N][N],b[N][N];
int front[N*2],next[M*4],to[M*4],tot,flow[M*4],pre[N*2],from[M*4];
double cost[M*4],dis[N*2];
int g[N*2];
queue<int>q;
bool v[N*2];
void add(int u,int v,int w,double val)
{
    to[++tot]=v; next[tot]=front[u]; front[u]=tot; flow[tot]=w; cost[tot]=val; from[tot]=u;
    to[++tot]=u; next[tot]=front[v]; front[v]=tot; flow[tot]=0; cost[tot]=-val; from[tot]=v;
}
bool spfa()
{
    for(int i=0;i<=2*n+1;i++) dis[i]=-1e9;
    memset(v,false,sizeof(v));
    memset(g,0,sizeof(g));
    q.push(src); v[src]=true; dis[src]=0;
    int now,t;
    while(!q.empty())
    {
        now=q.front(); q.pop(); v[now]=false;
        for(int i=front[now];i;i=next[i])
        {
            t=to[i];
            if(dis[t]<dis[now]+cost[i]&&flow[i]>0)
            {
                dis[t]=dis[now]+cost[i];
                pre[t]=i;
                if(!v[t])
                {
                    v[t]=true;
                    g[t]++;
                    if(g[t]>n)
                    {
                        printf("xun huan\n");
                        exit(0);
                    }
                    q.push(t);
                }
            }
        }
    }
    return dis[decc]!=-1e9;
}
double check(double k)
{
    double tmp=0; bool ok=false;
    memset(front,0,sizeof(front));
    tot=1;
    for(int i=1;i<=n;i++) add(src,i,1,0);
    for(int i=1;i<=n;i++) add(n+i,decc,1,0);
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
        add(i,j+n,1,(double)a[i][j]-k*b[i][j]);
    while(spfa())
    {
        if(tmp+dis[decc]>=0)
        {
            ok=true;
            tmp+=dis[decc];
            for(int i=pre[decc];i;i=pre[from[i]])
            {
                flow[i]--;flow[i^1]++;
            }
        }
        else return false;
    }
    return ok;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      scanf("%d",&a[i][j]);
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      scanf("%d",&b[i][j]);
    src=0,decc=n<<1|1;
    double l=0,r=1000000,mid;
    while(abs(r-l)>eps)
    {
        mid=(l+r)/2;
        if(check(mid)) ans=mid,l=mid+eps;
        else r=mid-eps;
    }
    printf("%.6lf",ans);
    return 0;
}
时间: 2024-10-18 23:37:51

[Sdoi2017]新生舞会的相关文章

[BZOJ4819][SDOI2017]新生舞会

[BZOJ4819][SDOI2017]新生舞会 bzoj luogu 题意 有\(n\)个男孩子和\(n\)个女孩子.他们之间要两两结伴跳舞. 已知第\(i\)个男孩子和第\(j\)个女孩子结伴跳舞会有两个参数\(a_{i,j}\)和\(b_{i,j}\). 现在要求一个安排方案使得\(a_{i,j}\)的总和除以\(b_{i,j}\)的总和的商尽量大. 形式化地,就是求一个长度为\(n\)的排列\(\{p_i\}\),最大化\(L=\frac{\sum_{i=1}^{n}a_{i,p_i}}

bzoj 4819: [Sdoi2017]新生舞会

Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度.Cathy还需要考虑两个人一起跳舞是否方便, 比如身高体重差别会不会太大,计算得出 b[i][j],表示第i个男生和第j个女生一起跳舞时的不协调程度.当然, 还需要考虑很多其他问题.Cathy

【bzoj4819】[Sdoi2017]新生舞会 分数规划+费用流

题目描述 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度.Cathy还需要考虑两个人一起跳舞是否方便,比如身高体重差别会不会太大,计算得出 b[i][j],表示第i个男生和第j个女生一起跳舞时的不协调程度.当然,还需要考虑很多其他问题.Cathy想先用一个程序通过a

BZOJ4819: [Sdoi2017]新生舞会(01分数规划)

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1029  Solved: 528[Submit][Status][Discuss] Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度.Cathy

codevs 5965 [SDOI2017]新生舞会

分数规划的裸题. 不会分数规划的OIer.百度:胡伯涛<最小割模型在信息学竞赛中的应用> /* TLE1: last:add(i,j+n,1e9,(real)((real)a[i][j]-ans*(real)b[i][j])); now :add(i,j+n,1,(real)((real)a[i][j]-ans*(real)b[i][j])); TLE2: last:real l=eps,r=(real)u/(real)v,mid,ans=0,now; now :real l=0,r=(rea

[Libre][SDOI2017]新生舞会

分数规划模板题 , 会写就能A #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<map> #include<queue> #include<vector> #include<cstdio> using namespace std; typedef long long ll; const int N

4819: [Sdoi2017]新生舞会

题目 https://www.lydsy.com/JudgeOnline/problem.php?id=4819 思路 分数规划的模板题?(好菜呀) 假如n=3吧(懒得写很长的式子) \(c=\frac{a_1+a_2+a_3}{b_1+b_2+b_3}\) 我们先二分一下,变为判定性问题 c是否大于等于xxxx \(c>=\frac{a_1+a_2+a_3}{b_1+b_2+b_3}\) \((b_1+b_2+b_3)*c>=a_1+a_2+a_3\) \(0>=(a_1-c*b_1)

P3705 [SDOI2017]新生舞会 分数规划 费用流

#include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #incl

BZOJ4819 新生舞会

4819: [Sdoi2017]新生舞会 Time Limit: 10 Sec  Memory Limit: 128 MB Description 学校组织了一次新生舞会,Cathy作为经验丰富的老学姐,负责为同学们安排舞伴.有n个男生和n个女生参加舞会 买一个男生和一个女生一起跳舞,互为舞伴.Cathy收集了这些同学之间的关系,比如两个人之前认识没计算得出 a[i][j] ,表示第i个男生和第j个女生一起跳舞时他们的喜悦程度.Cathy还需要考虑两个人一起跳舞是否方便, 比如身高体重差别会不会