题意:给出n个点 要求取k个点 这k个点中 距离最小的两个点要求距离最大
拿到手看不出是最大团 也看不出是二分答案(第一次用)
因为答案必然存在 一定有一个最值 所以用二分答案来做
最大距离为根号二乘10000 所以R=20000
且R-L>1e-4;
#include<bits/stdc++.h> using namespace std; #define N 60 int n; int mp[N][N]; int ans; int alt[N][N]; int Max[N]; struct { int x,y; }a[N]; bool dfs(int cur,int tot)//cur是s1集合的个数 { if(0==cur) { if(tot>ans) { ans=tot;return true; } return false; } for(int i=0;i<cur;i++) { if( tot+cur-i<=ans )return false; int u=alt[tot][i]; if( Max[u]+tot<=ans )return false; int next=0; for(int j=i+1;j<cur;j++) if(mp[u][ alt[tot][j] ])alt[tot+1][next++]=alt[tot][j]; if(dfs(next,tot+1)) return 1; } return 0; } int maxclique(void) { ans=0; memset(Max,0,sizeof(Max)); for(int i=n-1;i>=0;i--) { int cur=0; for(int j=i+1;j<n;j++)if(mp[i][j])alt[1][cur++]=j;//1为s1集合 dfs(cur,1); Max[i]=ans; } return ans; } void built(double mid) { for(int i=0;i<n;i++) for(int j= 0;j<n;j++) { double t=sqrt( (a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y) ); if( t>=mid )mp[i][j]=1; else mp[i][j]=0; } } int main() { int k; while(2==scanf("%d%d",&n,&k)) { for(int i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y); double L=0,R=20000; while(R-L>1e-4) { double mid=(L+R)/2; built(mid); if(maxclique()>=k)L=mid; else R=mid; } printf("%.2lf ",L); } return 0; }