maximum shortest distance
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1777 Accepted Submission(s): 589
Problem Description
There are n points in the plane. Your task is to pick k points (k>=2), and make the closest points in these k points as far as possible.
Input
For each case, the first line contains two integers n and k. The following n lines represent n points. Each contains two integers x and y. 2<=n<=50, 2<=k<=n, 0<=x,y<10000.
Output
For each case, output a line contains a real number with precision up to two decimal places.
Sample Input
3 2
0 0
10 0
0 20
Sample Output
22.36
Author
alpc50
题意:
给出n个点,问从中取哪k个点使得这k个点中每两个点之间的距离的最小值最大,输出这个距离。
代码:
//求最小值最大一般用二分。此题求出每两点之间的距离,然后二分距离,两点之间的距离大于等于此二分值的点之间连线, //重新建图,求新图的最大团是否大于等于k。这道题可以不直接二分距离,给距离排序二分下标即可。套最大团模板。 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int n,best,m; int mp[52][52],num[52]; double dis[2502],tmp[52][52],x[52],y[52]; bool dfs(int s[],int sum,int cnt) { if(sum==0){ if(cnt>best){ best=cnt; return 1; } return 0; } int t[102]; for(int i=0;i<sum;i++){ if(cnt+(sum-i)<=best) return 0; if(cnt+num[s[i]]<=best) return 0; int k=0; for(int j=i+1;j<sum;j++){ if(mp[s[i]][s[j]]) t[k++]=s[j]; } if(dfs(t,k,cnt+1)) return 1; } return 0; } bool Maxt(int M) { //if(n<=0) return 0; int s[102]; best=0; memset(mp,0,sizeof(mp)); for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) if(tmp[i][j]>=dis[M]) mp[i][j]=mp[j][i]=1; for(int i=n-1;i>=0;i--){ int k=0; for(int j=i+1;j<n;j++){ if(mp[i][j]) s[k++]=j; } dfs(s,k,1); num[i]=best; if(best>=m) return true; } return false; } int main() { while(~scanf("%d%d",&n,&m)){ int cnt=0; for(int i=0;i<n;i++){ scanf("%lf%lf",&x[i],&y[i]); tmp[i][i]=0; for(int j=0;j<i;j++) dis[cnt++]=tmp[i][j]=tmp[j][i]=((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); } sort(dis,dis+cnt); int ans=0; int L=0,R=cnt-1,M; while(L<=R){ M=(L+R)/2; if(Maxt(M)) {L=M+1;ans=M;} else R=M-1; } printf("%.2lf\n",sqrt(dis[ans])); } return 0; }