zoukankan      html  css  js  c++  java
  • BZOJ4819:[SDOI2017]新生舞会

    4819: [Sdoi2017]新生舞会

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 783  Solved: 396
    [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
     
    思路{
       比较裸的分数规划吧。。。
       由于昨天HN女队出了一道最大权闭合子图+分数规划,辣鸡的我没有看出来.就决心练一练.
       首先这是个二分图。虚拟源汇点连容量为1的边,考虑怎么得解。
       分数规划的套路是∑ai/∑bi=g,移项得∑ai-g*∑bi=0然后二分答案g都可以了;
       由于最大化g,考虑最大费用最大流,那么每两个连(-ai+g*bi)的边,直接费用流即可.
    }
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #define inf (1<<30)
    #define il inline
    #define RG register
    #define db double
    #define LL long long
    #define maxx 301
    using namespace std;
    struct ed{int nxt,to,c;db w;}e[maxx*maxx*6];
    int head[maxx*2],tot;
    void add(int u,int v,int c,db w){
    	e[tot].to=v;e[tot].nxt=head[u];
    	e[tot].c=c;e[tot].w=w;head[u]=tot++;
    }
    void ADD(int u,int v,int c,db w){
    	add(u,v,c,w);
    	add(v,u,0,-w);
    }
    int pre[maxx],flow;
    db dis[maxx],ans;
    bool in[maxx];
    queue<int>que;
    bool SPFA(int s,int t){
    	memset(dis,127,sizeof(dis));memset(in,false,sizeof(in));db SS=dis[0];
    	que.push(s),in[s]=true;dis[s]=0;
    	while(!que.empty()){
    		int u=que.front();que.pop(),in[u]=false;
    		for(int i=head[u];i!=-1;i=e[i].nxt){
    			if((!e[i].c)||dis[e[i].to]<=dis[u]+e[i].w)continue;
    			int v=e[i].to;dis[v]=dis[u]+e[i].w;
    			pre[v]=i;
    			if(!in[v])in[v]=true,que.push(v);
    		}
    	}if(dis[t]==SS)return false;
    	return true;
    }
    db get(int s,int t){
    	int u,p,sum=66666666;db Ans=0;
    	for(u=t;u!=s;u=e[p^1].to)p=pre[u],sum=min(sum,e[p].c);
    	for(u=t;u!=s;u=e[p^1].to)p=pre[u],e[p].c-=sum,e[p^1].c+=sum,Ans+=sum*e[p].w;
    	flow+=sum;return Ans;
    }
    db mincostflow(int s,int t){flow=0;ans=0.000;
    	while(SPFA(s,t))ans+=get(s,t);return ans;
    }
    int n,a[maxx][maxx],b[maxx][maxx];
    #define eps 0.0000001
    il void work(){
    	scanf("%d",&n);
    	for(RG int i=1;i<=n;++i)
    		for(RG int j=1;j<=n;++j)scanf("%d",&a[i][j]);
    	for(RG int i=1;i<=n;++i)
    		for(RG int j=1;j<=n;++j)scanf("%d",&b[i][j]);
    	db l=0.000,r=1000000.000;
    	while(r-l>eps){
    		memset(head,-1,sizeof(head));tot=0;
    		db mid=(l+r)/2;for(int i=1;i<=n;++i)ADD(0,i,1,0);
    		for(int i=n+1;i<=(n<<1);++i)ADD(i,((n<<1)|1),1,0);
    		for(int i=1;i<=n;++i)
    		for(int j=1;j<=n;++j)ADD(i,n+j,1,-a[i][j]+b[i][j]*mid);
    		db aa=-mincostflow(0,((n<<1)|1));
    		if(aa>0)l=mid+eps;else r=mid-eps;
    	}printf("%.6lf",(l+r)/2);
    }
    int main(){
        work();
        return 0;
    }
    
  • 相关阅读:
    复利计算4.0单元测试(c语言)
    操作系统之“实验一”
    操作系统cmd算法
    <构建之法>之第一二三章的感悟
    assertion的语法和语义
    java对象的内存分配
    Oracle Berkeley DB Java 版
    acid数据库事务正确执行的四个基本要素的缩写编辑本义项
    volatile-java关键字
    Heritrix源码分析(十五)
  • 原文地址:https://www.cnblogs.com/zzmmm/p/7151015.html
Copyright © 2011-2022 走看看