POJ 1981 Circle and Points 计算几何

题目大意

给出平面上的一些点,求一个单位圆最多能够覆盖多少点。

思路

数据范围300,但是没有用,多组数据就是要卡O(n3),然而常数优化的比较好的话在POJ能过,但是BZ上还是过不了。我们需要寻找一种O(n2logn)的做法。

做法就是枚举每个点,做一个一这个点为圆心的单位圆。之后将所有在这个圆里的点弄出来,以这些点为圆心做单位圆,与开始的单位圆会产生一段圆弧,最后求哪一段圆弧被覆盖的次数最多就是答案。

CODE

O(n3)水过版

#define _CRT_SECURE_NO_WARNINGS

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 510
#define EPS 1e-7
using namespace std;

struct Point{
    double x, y;

    Point(const double &_, const double &__):x(_), y(__) {}
    Point() {}

    Point operator +(const Point &a)const {
        return Point(x + a.x, y + a.y);
    }
    Point operator -(const Point &a)const {
        return Point(x - a.x, y - a.y);
    }
    Point operator *(const double &a)const {
        return Point(x * a, y * a);
    }
    Point operator /(const double &a)const {
        return Point(x / a, y / a);
    }

    void Read() {
        scanf("%lf%lf", &x, &y);
    }
}point[MAX];

inline double Calc(const Point &p1, const Point &p2)
{
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

inline Point Change(const Point &v)
{
    return Point(-v.y, v.x);
}

int points;
bool v[MAX];

int stack[MAX], top;

inline int GetAns(const Point &p1, const Point &p2)
{
    double dis = Calc(p1, p2) / 2;
    if(dis > 1.0)   return 0;
    Point o = Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2) + (Change(p1 - p2) / (dis * 2)) * sqrt(1 - dis * dis);
    int re = 0;
    for(int i = 1; i <= top; ++i)
        re += Calc(point[stack[i]], o) <= 1.0 + EPS;
    return re + 1;
}

int main()
{
    while(scanf("%d", &points), points) {
        for(int i = 1; i <= points; ++i)
            point[i].Read();
        int ans = 1;
        for(int i = 1; i <= points; ++i) {
            top = 0;
            for(int j = 1; j <= points; ++j)
                if(i != j && Calc(point[i], point[j]) < 2.0)
                    stack[++top] = j;
            for(int j = 1; j <= top; ++j)
                ans = max(ans, GetAns(point[i], point[stack[j]]));
        }
        printf("%d\n", ans);
    }
    return 0;
}
时间: 2024-10-09 13:44:31

POJ 1981 Circle and Points 计算几何的相关文章

POJ 1981 Circle and Points

//对于任意一点已经覆盖了一些点的圆,都可以通过对圆进行偏移,以使其在保证已覆盖的点的基础上,覆盖更多的点 //对这偏移进行到极限,就是刚好使两点在圆上 //其实这题的思路和POJ1106是差不多的,只不过在看到聚会范围在[0,10]的时候想到随机算法去了 //还有一种n^2logn的做法,学习了一下圆上弧被覆盖次数的标记 #include<stdio.h> #include<algorithm> #include<math.h> using namespace std

POJ 3090 Visible Lattice Points 欧拉函数

链接:http://poj.org/problem?id=3090 题意:在坐标系中,从横纵坐标 0 ≤ x, y ≤ N中的点中选择点,并且这些点与(0,0)的连点不经过其他的点. 思路:显而易见,x与y只有互质的情况下才会发生(0,0)与(x,y)交点不经过其他的点的情况,对于x,y等于N时,可以选择的点均为小于等于N并且与N互质的数,共Euler(N)个,并且不重叠.所以可以得到递推公式aa[i]=aa[i]+2*Euler(N). 代码: #include <iostream> #in

POJ 3090 Visible Lattice Points

Description A lattice point (x, y) in the first quadrant (x and y are integers greater than or equal to 0), other than the origin, is visible from the origin if the line from (0, 0) to (x, y) does not pass through any other lattice point. For example

POJ 3090 Visible Lattice Points 法雷级数

题目来源:POJ 3090 Visible Lattice Points 题意:哪些点可以看到 思路: F1: 0/1 1/1 F2: 0/1 1/2 1/1 F3: 0/1 1/3 1/2 2/3 1/1 F4: 0/1 1/4 1/3 1/2 2/3 3/4 1/1 F5: 0/1 1/5 1/4 1/3 2/5 1/2 3/5 2/3 3/4 4/5 1/1 F6:0/1 1/6 1/5 1/4 1/3 2/5 1/2 3/5 2/3 3/4 4/5 5/6 1/1 法雷级数 可以看到的那

poj 3090 Visible Lattice Points 法雷级数||打表

由于图像关于对角线对称,所以我们只看下三角区域.将x轴看做分母,被圈的点看成分子 依次是{1/2},{1/3,1/2},{1/4,3/4},{1/5,2/5,3/5,4/5} 写成前缀和的形式就是 {1/2},{1/2,1/3,2/3},{1/2,1/3,1/3,1/4,3/4},{1/2,1/3,1/3,1/4,3/4,1/5,2/5,3/5,4/5} 发现,这就是一个法雷级数,即第k项增加的数就是phi[k].最后的答案*2+(0,1)+(1,0),(1,1)三个点就好了 #include

poj1981 Circle and Points 单位圆覆盖问题

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Circle and Points Time Limit: 5000MS   Memory Limit: 30000K Total Submissions: 6850   Accepted: 2443 Case Time Limit: 2000MS Description You are given N points in the xy-plane. You have a cir

POJ 1981 最大点覆盖问题(极角排序)

Circle and Points Time Limit: 5000MS   Memory Limit: 30000K Total Submissions: 8346   Accepted: 2974 Case Time Limit: 2000MS Description You are given N points in the xy-plane. You have a circle of radius one and move it on the xy-plane, so as to enc

【POJ 1981 】Circle and Points

当两个点距离小于直径时,由它们为弦确定的一个单位圆(虽然有两个圆,但是想一想知道只算一个就可以)来计算覆盖多少点. #include <cstdio> #include <cmath> #define N 301 #define eps 1e-5 using namespace std; int n,ans,tol; double x[N],y[N],dx,dy; inline double sqr(double x) { return x*x; } inline double d

POJ - 1981 :Circle and Points (圆的扫描线) hihocoder1508

题意:给定N个点,然后给定一个半径为R的圆,问这个圆最多覆盖多少个点. 思路:在圆弧上求扫描线. hihocoder1508的代码. #include<bits/stdc++.h> #define pdd pair<double,int> #define f first #define s second #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=200010; co