基础算法之分治算法(求平面最近点对问题)

这个博客写的还不错
大概是打算清理一下基础算法的知识盲区吧,就去过了一遍
平面最近点对问题刷题以来一共遇到两次。。。可能我数学题写少了
Quoit Design ZOJ - 2107
这大概是一个模板入门题吧
注意的是要你输出半径,所以你求出最近点对距离后还要除于2

struct node{
    double x,y;
}point[maxn];
int cup[maxn];
bool cmpx(node a,node b){
    if(a.x==b.x){
        return a.y<b.y;
    }else{
        return a.x<b.x;
    }
}
bool cmpy(int a,int b){
    if(point[a].y==point[b].y){
        return point[a].x<point[b].x;
    }else{
        return point[a].y<point[b].y;
    }
}
double get_dis(int a,int b){
    return sqrt(pow(point[a].x-point[b].x,2)+pow(point[a].y-point[b].y,2));
}
double closest_pair(int l,int r){
    if(r==l+1){
        return get_dis(l,r);
    }else if(r==l){
        return inf*1.0;
    }else if(r==l+2){
        return min(get_dis(l,r),min(get_dis(l,l+1),get_dis(l+1,r)));
    }
    int mid=l+r>>1;
    double ans=min(closest_pair(l,mid),closest_pair(mid+1,r));
    int num=0;
    rep(i,l,r){
        if(point[i].x>=point[mid].x-ans&&point[i].x<=point[mid].x+ans){
            cup[++num]=i;
        }
    }
    sort(cup+1,cup+num+1,cmpy);
    rep(i,1,num){
        rep(j,i+1,num){
            if(point[cup[j]].y-point[cup[i]].y>=ans){
                break;
            }
            ans=min(ans,get_dis(cup[i],cup[j]));
        }
    }
    return ans;
}
void solve(){
    int n;while(~scanf("%d",&n)&&n){
        rep(i,1,n){
            scanf("%lf %lf",&point[i].x,&point[i].y);
        }
        sort(point+1,point+n+1,cmpx);
        printf("%.2f\n",closest_pair(1,n)/2);
    }
}

Raid POJ - 3714
这个题不同的地方是每个人要到指定的地方,求出哪个人可以最快到达一个地方(也就是求哪个人到炮台最近,有很多炮台)
给人和炮台标记不同的记号我想到了,但我却一直在想怎么在搜距离时区分开。。。后来发现我直接修改dis函数就好了 对于记号相同的直接记作无穷大距离就好了…

struct node{
    double x,y;
    int id;
}point[maxn];
int cup[maxn];
bool cmpx(node a,node b){
    if(a.x==b.x){
        return a.y<b.y;
    }else{
        return a.x<b.x;
    }
}
bool cmpy(int a,int b){
    if(point[a].y==point[b].y){
        return point[a].x<point[b].x;
    }else{
        return point[a].y<point[b].y;
    }
}
double get_dis(int a,int b){
    return point[a].id==point[b].id ? 5e11 : sqrt(pow(point[a].x-point[b].x,2)+pow(point[a].y-point[b].y,2));
}
double closest_pair(int l,int r){
    if(r==l+1){
        return get_dis(l,r);
    }else if(r==l){
        return 1.0*5e11;
    }else if(r==l+2){
        return min(get_dis(l,r),min(get_dis(l,l+1),get_dis(l+1,r)));
    }
    int mid=l+r>>1;
    double ans=min(closest_pair(l,mid),closest_pair(mid+1,r));
    int num=0;
    rep(i,l,r){
        if(point[i].x>=point[mid].x-ans&&point[i].x<=point[mid].x+ans){
            cup[++num]=i;
        }
    }
    sort(cup+1,cup+num+1,cmpy);
    rep(i,1,num){
        rep(j,i+1,num){
            if(point[cup[j]].y-point[cup[i]].y>=ans){
                break;
            }
            ans=min(ans,get_dis(cup[i],cup[j]));
        }
    }
    //de(l),de(r),de(ans),de("pppppppppp");
    return ans;
}
void solve(){
    int n=read();
    rep(i,1,n){
        scanf("%lf %lf",&point[i].x,&point[i].y);
        point[i].id=-1;
    }
    rep(i,n+1,2*n){
        scanf("%lf %lf",&point[i].x,&point[i].y);
        point[i].id=1;
    }
    sort(point+1,point+n*2+1,cmpx);
    printf("%.3f\n",closest_pair(1,n*2));
    
}

你可能感兴趣的:(分治,计算几何)