列表

详情


NC232892. Nearest Point

描述

Nearest point is a classical problem in computational geometry. Given a set S of n points p_1, . . . , p_n, p_j is the nearest point of pi if  , and (2) for any other point  (p_i , p_k) , where dis (p_1, p_2) is defined as  in a 2-D space. 
Calculating the neatest point is known to be difficult. Therefore, there are many heuristic methods proposed. The following describes one of these algorithms:
         • Step1: A random angle α is uniformly selected from range .
         • Step2: All points in S are rotated α counterclockwise centered on the origin (0, 0).
          Step3: For each point p_i , the algorithm takes the point that is closest to p_i on the x-coordinate, i.e., the point  that minimizes . If there are multiple such points, the point with the smallest index will be selected. 
For example, suppose there are three points , , and  in set S
        1. When α is selected as 0, the coordinates of these three points after the rotation are (1, 1),(3, 3),(0, 2), respectively, and thus the nearest points to p_1, p_2, p_3 found by the algorithm are p_3, p_1, p_1, respectively. 
        2. When α is selected as  , the coordinates of these three points after the rotation are , and thus the nearest points are p_2, p_1, p_1, respectively.
Now, given the n points p_1, . . . , p_n in S, your task is to output an  matrix w, where  represents the probability for the algorithm to take p_j as the nearest point of p_i

输入描述

The first line contains a single integer , the number of points in S.
 Then n lines follow, each line contains two integers x_i and 
The input guarantees that each given point is different from the other

输出描述

Output n lines, each with n float numbers. The j-th number in the i-th line represents the probability for p_j to be returned as the nearest point by the algorithm. 
Note that for each i, the i-th number in the i-th line is always 0. 
Your result is judged as correct if for each probability, either the relative error or the absolute error comparing with the standard output is at most
Note: The space at the end of a line will be ignored. 

示例1

输入:

3
1 1
3 3
0 2

输出:

0.00000000 0.29516721 0.70483279
0.57797916 0.00000000 0.42202084
0.75000004 0.24999996 0.00000000

示例2

输入:

3
1 1
2 2
3 3

输出:

0.00000000 1.00000000 0.00000000
1.00000000 0.00000000 0.00000000
0.00000000 1.00000000 0.00000000

示例3

输入:

5
8 10
9 75
810 9
7 5
810 975

输出:

0.00000000 0.00909209 0.00396988 0.98570675 0.00123125
0.87050435 0.00000000 0.05126782 0.05576056 0.02246725
0.01389151 0.27660743 0.00000000 0.27929864 0.43020240
0.98698866 0.00782892 0.00395991 0.00000000 0.00122250
0.00558540 0.30017070 0.59898322 0.09526066 0.00000000

说明:

810975,萌新怎么听不懂!922768,萌新怎么不知道?

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 2020ms, 内存消耗: 744K, 提交时间: 2022-09-11 12:50:06

#include<iostream>
#include<cstdio>
#include<cmath>
#include<map>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;

typedef long long LL;
const int N=60;
const double eps = 1e-11;
const double pi = acos(-1);

int dcmp(double x, double y){
    if(fabs(x - y) < eps) return 0;
    if(x < y) return -1;
    return 1;
}
int sign(double x){
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    return 1;
}

struct point{
    double x, y;
    int id;
    bool operator == (const point a) const {
        return !dcmp(x, a.x) && !dcmp(y, a.y);
    }
};
point operator + (point a, point b) { return {a.x + b.x, a.y + b.y}; }
point operator - (point a, point b) { return {a.x - b.x, a.y - b.y}; }
point operator * (point a, double b) { return {a.x * b, a.y * b}; }
point operator / (point a, double b) { return {a.x / b, a.y / b}; }

double cross(point a, point b) { return a.x * b.y - a.y * b.x; }
double dot(point a, point b) { return a.x * b.x + a.y * b.y; }
double angle(point a) { return atan2(a.y, a.x); }
point rotate(point a, double rad) { return {a.x * cos(rad) - a.y * sin(rad), a.x * sin(rad) + a.y * cos(rad)}; }


point P[N];
point tmp[N];
double divi[N * N * 4];
int cnt;
double ans[N][N];


void add(point v)
{
    if(v.x < 0) v.x = -v.x, v.y = -v.y;
    divi[cnt++] = pi / 2 - angle(v);
    divi[cnt] = divi[cnt - 1] + pi, cnt++; // 原句是 divi[cnt++] = divi[cnt - 1] + pi;
}

double idx;
bool cmp(const point a, const point b){
    double A = fabs(a.x - idx), B = fabs(b.x - idx);
    if(dcmp(A, B)) return dcmp(A, B) < 0;
    return a.id < b.id;
}

int n;
int find(double rad, int i)
{
    int pos = 0;
    for(int j=0; j<n; j++)
        if(j != i)
            tmp[pos] = rotate(P[j], rad), tmp[pos++].id = j;

    idx = rotate(P[i], rad).x;

    sort(tmp, tmp + pos, cmp);

    return tmp[0].id;
}


int main()
{
    scanf("%d", &n);
    for(int i=0; i<n; i++) scanf("%lf %lf", &P[i].x, &P[i].y);

    for(int i=0; i<n; i++)
    {
        cnt = 0;
        divi[cnt++] = 0;
        divi[cnt++] = pi * 2;
        for(int j=0; j<n; j++)
            if(i != j)
                for(int k=j + 1; k<n; k++)
                    if(k != i)
                    {
                        if(sign(cross(P[j] - P[i], P[k] - P[i]))== 0) continue;//不要也可以ac
                        add(P[k] - P[j]);
                        add((P[k] + P[j]) / 2 - P[i]);
                    }
        sort(divi, divi + cnt, less<double> ());

        for(int j=1; j<cnt; j++){
            double mid = (divi[j] + divi[j - 1]) / 2;
            ans[i][find(mid, i)] += (divi[j] - divi[j - 1]);
        }
    }

    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
            printf("%.11f ", ans[i][j] / pi / 2);
        printf("\n");
    }

    system("pause");
    return 0;
}

C++ 解法, 执行用时: 49ms, 内存消耗: 584K, 提交时间: 2022-02-09 15:41:29

#include<bits/stdc++.h>
using namespace std;
const double Pi=acos(-1);
struct Point
{
    int x,y;
    Point operator +(const Point&a)const{return {x+a.x,y+a.y};}
    Point operator -(const Point&a)const{return {x-a.x,y-a.y};}
    double v_deg()const{return atan2(x,-y);}
};
int main()
{
    int n;scanf("%d",&n);
    vector<double> d,ans(n);
    vector<Point> a(n),b(n);
    for (auto &p:a) scanf("%d%d",&p.x,&p.y);
    auto Cross = [&](double x, double y, Point c) { return abs(x * c.x + y * c.y); };
    for(int i=0;i<n;++i)
    {
        ans.assign(n,0),d={-Pi,Pi};
        for(int j=0;j<n;++j)b[j]=a[j]-a[i];
        for(int j=0;j<n;++j)
            for(int k=j+1;k<n;++k)
            d.push_back((b[j]-b[k]).v_deg()),d.push_back((b[j]+b[k]).v_deg());
        for(auto t:d)d.push_back(t+(t<0?Pi:-Pi));
        sort(d.begin(),d.end());
        for(int t=1;t<d.size();++t)
        {
            if(d[t]-d[t-1]<1e-11)continue;
            int k=0;double L=d[t]-d[t-1], m=d[t-1]+L*0.5,x=cos(m),y=sin(m),mn=1e18,temp;
            for(int j=0;j<n;++j)
                if(j!=i&&mn-(temp=Cross(x,y,b[j]))>1e-9)mn=temp,k=j;
            ans[k]+=L;
        }
        for(int j=0;j<n;++j)
            printf("%.9f%c",i==j?0:ans[j]/Pi*0.5," \n"[j==n-1]);
    }
}

上一题