高效算法设计专项:LA 2963

来源:互联网 发布:mac os x 卸载 编辑:程序博客网 时间:2024/05/21 14:01

刚开始完全没思路,看了训练指南上的提示说是扫描法,然后往这方面想。仔细分析题目发现可以用O(n^2)的时间解决。不难发现可能的结果只可能是n个点两两距离的,然后可以从小到大扫描这n*(n-1)/2条边,然后维护当前符合条件的planet的个数。需要注意处理边长相等的情况。

#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>using namespace std;#define M 1010const double eps=1e-6;int dcmp(double x){    if(fabs(x)<eps) return 0;    else return x<0?-1:1;}struct point{    int x,y,z,p;} a[M];struct edge{    int u,v;    double l;    edge(int u=0,int v=0,double l=0):u(u),v(v),l(l){}    bool operator<(const edge& tmp) const    {return dcmp(l-tmp.l)<0;}} e[M*M];double length(int i,int j){    int x=a[i].x-a[j].x,y=a[i].y-a[j].y,z=a[i].z-a[j].z;    return sqrt(x*x+y*y+z*z);}int n,m;int c[M];int main(){    freopen("in.txt","r",stdin);    while(scanf("%d",&n)!=EOF)    {        for(int i=0;i<n;i++)        {            scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].z,&a[i].p);            c[i]=1;        }        m=0;        for(int i=0;i<n;i++)        {            for(int j=i+1;j<n;j++)            {                e[m++]=edge(i,j,length(i,j));            }        }        sort(e,e+m);        int ans=0,cur=0;        double len=0;        for(int i=0;i<m;i++)        {            int u=e[i].u,v=e[i].v;            double l=e[i].l;            if(a[u].p!=a[v].p)            {                c[u]--;                c[v]--;                if(c[u]==-1) cur++;                if(c[v]==-1) cur++;            }            else            {                c[u]++;                c[v]++;                if(c[u]==0) cur--;                if(c[v]==0) cur--;            }            if(i!=m-1&&dcmp(l-e[i+1].l)==0) continue;            if(cur>ans)            {                ans=cur;                len=l;            }        }        printf("%d\n",ans);        printf("%.4f\n",len);    }    return 0;}


原创粉丝点击