zoukankan      html  css  js  c++  java
  • 灵魂宝石 BZOJ 2663

    灵魂宝石

    【问题描述】 

    “作为你们本体的灵魂,为了能够更好的运用魔法,被赋予了既小巧又安全的外形”

    我们知道,魔法少女的生命被存放于一个称为灵魂宝石(Soul Gem)的装置内。而有时,当灵魂宝石与躯体的距离较远时,魔法少女就无法控制自己的躯体了。在传说中,魔法少女Abel仅通过推理就得到了这个现象的一般法则,被称为Abel定理:存在宇宙常量R(是一个非负实数,或正无穷),被称为灵魂宝石常量,量纲为空间度量(即:长度)。如果某个魔法少女的灵魂宝石与她的躯体的距离严格超过R,则她一定无法控制自己的躯体;如果这个距离严格小于R,则她一定可以控制自己的躯体。(这里的距离指平面的 Euclid距离。) 

    注意:该定理不能预言距离刚好为R的情形。可能存在魔法少女A和B,她们离自己的灵魂宝石的距离都恰好为R,但是A可以控制自己的躯体,而B不可以。

    现在这个世界上再也没有魔法少女了,但是我们却对这个宇宙常量感兴趣。我们只能通过之前的世界遗留下来的数据来确定这个常量的范围了。

    每一组数据包含以下信息: 

    一共有N个魔法少女及她们的灵魂宝石,分别编号为1-N。

    这N个魔法少女所在的位置是(Xi, Yi)。 

    这N个灵魂宝石所在的位置是(xi, yi)。 

    此时恰好有 K个魔法少女能够控制自己的躯体。

    1.我们认为这个世界是二维的 Euclid 空间。

    2.魔法少女与灵魂宝石之间的对应关系是未知的。

    3.我们不知道是具体是哪 K个魔法少女能够控制自己的躯体。

    根据以上信息,你需要确定灵魂宝石常量 R可能的最小值 Rmin 和最大值Rmax。

    【输入格式】

    第一行包两个整数:N、K。 
    接下来N行,每行包含两个整数:Xi,Yi,由空格隔开。 
    再接下来N行,每行包含两个整数:xi,yi,由空格隔开。 

    【输出格式】

    输出两个量:Rmin、Rmax,中间用空格隔开。 
    Rmin 一定是一个非负实数,四舍五入到小数点后两位。 
    Rmax 可能是非负实数,或者是正无穷: 
    如果是非负实数,四舍五入到小数点后两位; 
    如果是正无穷,输出“+INF”(不包含引号)。

    【输入样例】

    2 1

    1 0

    4 0

    0 0

    4 4

    【输出样例】

    1.00 5.00

    【数据范围】

    对于100%的数据: 

    1 ≤ N ≤ 50,0 ≤ K ≤ N,-1000 ≤ xi,yi,Xi,Yi ≤ 1000。


    题解:

    题意:对于n个人与n个宝石,每个人需要各自匹配一1颗与其距离小于k的宝石,距离等于k的宝石可以自由选择是否匹配,求k的最小值与最大值

    那么最小值可以很容易想到二分,连接所有距离小于k的边,用二分图匹配检验,则为用最大匹配数求最小值

    然而最大值并不能直接像最小值一样求解,因为二分图求的是最大匹配,这一点模拟样例就可以得到

    于是考虑一点小小的转化

    最大值的检验中,我们将距离大于等于k的边相连

    那么二分图匹配跑出的结果就是最大不匹配数

    总个数减去最大不匹配数即为最小匹配数

    利用最小匹配数就能最大值

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cstdio>
      6 #include<cmath>
      7 using namespace std;
      8 struct shape
      9 {
     10     double x, y;
     11 };
     12 int n, k;
     13 double l, r;
     14 double ans;
     15 int my[233];
     16 shape a[233];
     17 bool vis[233];
     18 int tot, to[10233], nex[10233], fir[233];
     19 inline double Dis(shape x, shape y)
     20 {
     21     return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y));
     22 }
     23 inline void Ins(int x, int y)
     24 {
     25     nex[++tot] = fir[x];
     26     fir[x] = tot;
     27     to[tot] = y;
     28 }
     29 bool Find(int u)
     30 {
     31     for(int i = fir[u]; i; i = nex[i])
     32     {
     33         int v = to[i];
     34         if(!vis[v])
     35         {
     36             vis[v] = true; 
     37             if(!my[v] || Find(my[v]))
     38             {
     39                 my[v] = u;
     40                 return true;
     41             }
     42         }
     43     }
     44     return false;
     45 }
     46 inline bool Checkmi(double x)
     47 {
     48     tot = 0;
     49     for(int i = 1; i <= n; ++i) my[i + n] = fir[i] = 0;
     50     for(int i = 1; i <= n; ++i)
     51         for(int j = n + 1; j <= n + n; ++j)
     52             if(Dis(a[i], a[j]) <= x)
     53                 Ins(i, j);
     54     int sum = 0;
     55     for(int i = 1; i <= n; ++i)
     56     {
     57         for(int j = 1; j <= n; ++j)
     58             vis[j + n] = false;
     59         if(Find(i)) ++sum;
     60     }
     61     if(sum < k) return true;
     62     return false;
     63 }
     64 inline bool Checkma(double x)
     65 {
     66     tot = 0;
     67     for(int i = 1; i <= n; ++i) my[i + n] = fir[i] = 0;
     68     for(int i = 1; i <= n; ++i)
     69         for(int j = n + 1; j <= n + n; ++j)
     70             if(Dis(a[i], a[j]) >= x)
     71                 Ins(i, j);
     72     int sum = 0;
     73     for(int i = 1; i <= n; ++i)
     74     {
     75         for(int j = 1; j <= n; ++j)
     76             vis[j + n] = false;
     77         if(Find(i)) ++sum;
     78     }
     79     if(sum < n - k) return false;
     80     return true;
     81 }
     82 int main()
     83 {
     84 //    freopen("soulgem.in", "r", stdin), freopen("soulgem.out", "w", stdout);
     85     scanf("%d%d", &n, &k);
     86     for(int i = 1; i <= n + n; ++i)
     87         scanf("%lf %lf", &a[i].x, &a[i].y);
     88     l = 0, r = 3666;
     89     for(int i = 1; i <= 38; ++i)
     90     {
     91         double mi = (l + r) / 2.0;
     92         if(Checkmi(mi)) l = mi;
     93         else ans = mi, r = mi;
     94     }
     95     printf("%.2lf ", ans);
     96     ans = 3666;
     97     l = 0, r = 3666;
     98     for(int i = 1; i <= 38; ++i)
     99     {
    100         double mi = (l + r) / 2.0;
    101         if(Checkma(mi)) ans = mi, l = mi;
    102         else r = mi;
    103     }
    104     if(fabs(ans - 3666) <= 0.001) printf("+INF");
    105     else printf("%.2lf", ans);
    106 }
  • 相关阅读:
    angular div contenteditable 属性,实现数据双向绑定
    node最简单的本地服务搭建
    picker-view、微信小程序自定义时间选择器(非官方)
    微信小程序wx.switchTab跳转到tab页面后onLoad里面的方法不执行
    小程序拨号功能,小程序点击按钮实现打电话功能
    css换行后缩进,css缩进技巧
    小程序循环列表,点击展开收起/关闭效果
    最新前端面试题-前端必备技能-前端技术汇总
    mapreduce处理天气数据
    基于Canal的数据感知服务平台
  • 原文地址:https://www.cnblogs.com/lytccc/p/6221660.html
Copyright © 2011-2022 走看看