Description
【问题描述】
“作为你们本体的灵魂,为了能够更好的运用魔法,被赋予了既小巧又安全
的外形,„„”
我们知道,魔法少女的生命被存放于一个称为灵魂宝石(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。
Input
第一行包两个整数:N、K。
接下来 N行,每行包含两个整数:Xi , Yi ,由空格隔开。
再接下来N 行,每行包含两个整数:xi , yi ,由空格隔开。
Output
输出两个量:Rmin、Rmax,中间用空格隔开。
Rmin 一定是一个非负实数,四舍五入到小数点后两位。
Rmax 可能是非负实数,或者是正无穷:
如果是非负实数,四舍五入到小数点后两位;
如果是正无穷,输出“+INF”(不包含引号)。
Sample Input
1 0
4 0
0 0
4 4
Sample Output
HINT
对于100%的数据:
1 ≤ N ≤ 50,
0 ≤ K ≤ N,
-1000 ≤ xi, yi , Xi , Yi ≤ 1000。
一眼二分,然后再读题
话说这种题一看就是最大匹配吧。。。
首先第一个最小值很好想啊,二分枚举X,距离小于X连边,然后跑最大匹配,跑完看看匹配数>=k的话缩小上界,记录答案
然后最大值就把我卡住了。。。 真是代码1分钟,思考半小时,直接复制黏贴走一波(雾)
其实最大值也很好想,只是自己太SB,只用反过来即可
同样二分枚举X,向距离大于X连边,跑最大匹配,跑完看看匹配数>=n-k的话就扩大下界,记录答案
第一个都想出来了第二个还想半个小时我真是个SB
代码如下:
#include<cmath> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const double eps=1e-8; struct node{ int x,y,next; }a[3100];int len,last[3100]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } bool chw[51]; int match[51]; struct Coordinate { double x,y; }p[51],s[51]; double S(double X){return X*X;} double dis(double x1,double x2,double y1,double y2){return sqrt(S(x1-x2)+S(y1-y2));} int n,k; bool Married(int x) { for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(chw[y]==true) { chw[y]=false; if(match[y]==0||Married(match[y])==true) { match[y]=x; return true; } } } return false; } bool check(double x) { len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(dis(p[i].x,s[j].x,p[i].y,s[j].y)<=x) ins(i,j); memset(match,0,sizeof(match)); int sum=0; for(int i=1;i<=n;i++) { memset(chw,true,sizeof(chw)); if(Married(i)==true)sum++; } if(sum>=k)return true; return false; } bool examin(double x) { len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(dis(p[i].x,s[j].x,p[i].y,s[j].y)>=x) ins(i,j); memset(match,0,sizeof(match)); int sum=0; for(int i=1;i<=n;i++) { memset(chw,true,sizeof(chw)); if(Married(i)==true)sum++; } if(sum>=n-k)return false; return true; } int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y); for(int i=1;i<=n;i++)scanf("%lf%lf",&s[i].x,&s[i].y); double ans1; double l=0.0;double r=4000.0; while(l<r) { double mid=(l+r)/2; if(check(mid)==true)r=mid-eps,ans1=mid; else l=mid+eps; } printf("%.2lf ",ans1); if(n==k){printf("+INF\n");return 0;} double ans2; l=0.0,r=4000.0; while(l<r) { double mid=(l+r)/2; if(examin(mid)==true)r=mid-eps; else l=mid+eps,ans2=mid; } printf("%.2lf\n",ans2); return 0; }
by_lmy