您的位置:首页 > 其它

【二分+最大团】【HDU3585】【maximum shortest distance】

2015-07-05 13:31 405 查看
题目大意

在N个点钟 选出K个点 使得这K个点间的最小距离最大

二分距离,然后如果两点间距离小于它的边当做不存在,求出最大团,如果最大团>=K,向上缩小区间

< K , 向下缩小区间

OK~

#include<stdio.h>
#include<math.h>
#include<iostream>
#define eps 1e-7
using namespace std;

int n,k,vis[55],tmax,dp[55],ji;
int locat[55][2],map[55][55];
double dis[55][55],distan[2000];

int cmp(const void *a,const void*b)
{
return *(double *)a>*(double *)b?1:-1;
}

void build(int mid)
{
int i,f;
for(i=1;i<=n;i++)
{
for(f=1;f<=n;f++)
{
if(dis[i][f] >= distan[mid]-eps)
{
map[i][f]=1;
}
else
{
map[i][f]=0;
}
}
map[i][i]=0;
}
}

void dfs(int id,int cnt)
{
int tvis[55],i,f,able=0;
for(i=id+1;i<=n;i++)
{
if(1 == vis[i])
{
able++;
}
}
if(0 == able)
{
tmax=max(tmax,cnt);
}
if(cnt + able <= tmax)
{
return ;
}
for(i=1;i<=n;i++)
{
tvis[i]=vis[i];
}
for(i=id+1;i<=n;i++)
{
if(0 == tvis[i])
{
continue;
}
if(cnt +dp[i] <= tmax)
{
continue;
}
for(f=id+1;f<=n;f++)
{
vis[f]=tvis[f]&map[i][f];
}
dfs(i,cnt+1);
}
}

int max_clique()
{
int i,f;
tmax=1;
dp
=1;
for(i=n-1;i>=1;i--)
{
for(f=1;f<=n;f++)
{
vis[f]=map[i][f];
}
dfs(i,1);
dp[i]=tmax;
if(n == tmax)
{
return tmax;
}
}
return tmax;
}

double bs()
{
int l=0,r=ji,mid;
while(l != r-1)
{
mid=(l+r)>>1;
build(mid);
if(k <= max_clique())
{
l=mid;
}
else
{
r=mid;
}
}
return distan[l];
}

int main()
{
int i,f,g,sum;
while(scanf("%d%d",&n,&k)!=EOF)
{
ji=0;
for(i=1;i<=n;i++)
{
scanf("%d%d",&locat[i][0],&locat[i][1]);
}
for(i=1;i<=n;i++)
{
for(f=1;f<=n;f++)
{
sum=0;
for(g=0;g<2;g++)
{
sum+=(locat[i][g]-locat[f][g])*((locat[i][g]-locat[f][g]));
}
dis[i][f]=sqrt((double)sum);
if(i > f)
{
distan[ji]=dis[i][f];
ji++;
}
}
}
qsort(distan,ji,sizeof(distan[0]),cmp);
printf("%.2lf\n",bs());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: