zoukankan      html  css  js  c++  java
  • 【Earthquake, 2001 Open 】 0-1 分数规划

    71  奶牛施工队
    一场地震把约翰家园摧毁了,坚强的约翰决心重建家园。约翰已经修复了 N 个牧场,他需要再
    修复一些道路把它们连接起来。碰巧的是,奶牛们最近也成立了一个工程队,专门从事道路修复。而
    然,奶牛们很有经济头脑,如果无利可图,它们是不会干的。
    约翰和奶牛达成了协议,约翰向奶牛支付 F 元,奶牛负责修路,但不必修复所有道路,只要确保
    所有牧场连通即可。可供奶牛选择修复的道路有 M 条,第 i 条道路连接第 Ui 个牧场和第 Vi 个牧场,
    修复需要 Ti 分钟,支出成本为 Ci。保证连通所有牧场的道路修复方案总是存在的。奶牛们关注的是
    挣钱速度,即总利润和总施工时间的比值。请帮助奶牛们选择修复哪些道路,才能使它们在单位时间
    里的利润最大?
    输入格式
    • 第一行:三个整数 NM F, 1 N 400 , 1 M 10000 , 1 F 2 × 109
    • 第二行到第 M + 1 行:第 i + 1 行有四个整数 UiViCi Ti, 1 Ui,Vi N, 1 Ci,Ti
    2 × 109
    输出格式
    • 单个浮点数:表示施工队的最大挣钱速度,以四舍五入的方法保留四位小数,如果这个项目一
    定亏本,输出 0.0000
    样例输入
    5 5 100
    1 2 20 5
    1 3 20 5
    1 4 20 5
    1 5 20 5
    2 3 23 1
    样例输出
    1.0625
    解释
    修最后四条道路,成本总和为 83,时间总和
    为 16,所以单位时间的利润为 (100 83)/16 =
    1. 0625

    【分析】

      因为又是一题0-1分数规划,就再写一下。。

      其实就是个二分?

      二分答案mid,即要求[F-sigma(Ci) ]/sigma(Ti)>=mid

      就是F>=sigma(Ci+mid*Ti)

      右边尽量小就更有可能成立,就用最小1生成树krustal。

      嗯

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<queue>
     7 #include<cmath>
     8 using namespace std;
     9 #define Maxn 410
    10 #define Maxm 10010
    11 
    12 struct node
    13 {
    14     int x,y,a,b;
    15     double c;
    16 }t[Maxm*2];
    17 
    18 int fa[Maxn],n,m;
    19 double f;
    20 
    21 bool cmp(node x,node y) {return x.c<y.c;}
    22 
    23 int ffa(int x)
    24 {
    25     if(fa[x]!=x) return ffa(fa[x]);
    26     return fa[x];
    27 }
    28 
    29 bool check(double x)
    30 {
    31     for(int i=1;i<=m;i++) t[i].c=t[i].a+x*t[i].b;
    32     sort(t+1,t+1+m,cmp);
    33     double sum=0;int cnt=0;
    34     for(int i=1;i<=n;i++) fa[i]=i;
    35     for(int i=1;i<=m;i++)
    36     {
    37         if(ffa(t[i].x)!=ffa(t[i].y))
    38         {
    39             fa[ffa(t[i].x)]=ffa(t[i].y);
    40             cnt++;
    41             sum+=t[i].c;
    42         }
    43         if(cnt==n-1) break;
    44     }
    45     return (cnt==n-1)&&(f>=sum);
    46 }
    47 
    48 void ffind(double l,double r)
    49 {
    50     while(r-l>0.000001)
    51     {
    52         double mid=(l+r)/2;
    53         if(check(mid)) l=mid;
    54         else r=mid;
    55     }
    56     printf("%.4lf
    ",l);
    57 }
    58 
    59 int main()
    60 {
    61     double sm=0;
    62     scanf("%d%d%lf",&n,&m,&f);
    63     for(int i=1;i<=m;i++)
    64     {
    65         scanf("%d%d%d%d",&t[i].x,&t[i].y,&t[i].a,&t[i].b);
    66         sm+=t[i].a;
    67     }
    68     ffind(0,sm);
    69     return 0;
    70 }
    OwO

    2016-10-31 20:09:07

  • 相关阅读:
    🍖名称空间与作用域
    🍖文件打开模式 "t"
    🍖函数参数
    【转】LINQ中的Aggregate语法
    【转】c#中string.trimstart() 和string.trimend() 的用法
    1094 和为k的连续区间(暴力)
    1095 Anigram单词
    1031 骨牌覆盖 (斐波拉契数列)
    最长公共子序列(模板 LCSL)
    1092 回文字符串(LCSL_DP)
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6017197.html
Copyright © 2011-2022 走看看