hdu 3585 maximum shortest distance 二分小技巧

来源:互联网 发布:html5 php 交互 编辑:程序博客网 时间:2024/06/02 02:19

    这道题是学习了最大团过程中遇到的一道题目,最大团学习中的体会就是搜索的基本功还是不扎实,最大团是一个NP完全问题(不懂装懂了),现在还没多项式算法,只能靠启发式搜索或者是回溯来实现了。回溯法也可以通过各种剪枝来优化。

    回到这道题目,意思就是给定平面上一些点,求出K个点满足其实每个点的距离都大于M,求M.

    通过不断的二分距离,如果距离大于二分出来的距离,那么就建边,求出最大团,就是满足距离大于M的最大个数,然后就是无限TLE。因为我是通过直接二分它们之间的距离,但是这道题目的特殊性就在于,最终二分出来的值必定是某两个点之间的距离,我们具体在操作的时候相当于可以直接离散化,把所有的距离预处理出来,然后直接对这些个别距离进行二分。终于700ms+水过了。。。这个方法感觉非常实用的一个小技巧微笑。继续加油

 

 

#include<stdio.h>#include<math.h>#include<iostream>#define eps 1e-7using 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[n]=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;}


 

原创粉丝点击