挑战程序竞赛系列(84):3.6极限情况(1)
来源:互联网 发布:nginx动静分离配置 编辑:程序博客网 时间:2024/05/22 06:38
挑战程序竞赛系列(84):3.6极限情况(1)
传送门:POJ 1981: Circle and Points
题意:
平面上有N个点,给定半径为1的圆,最多能在圆内点的个数。
这种题目很大特色在于,如果枚举圆的圆心,那么在偌大的空间中,有无数个圆,显然是不现实的。所以得考虑极限情况,也就是找出一种特殊的状态,更新它们的集合,能够获得答案。
此题的极限情况为:当两个点在一个圆上时,最大值一定在于这种情况。因此,我们可以枚举两个点构成的圆,并且计算该圆内有多少个点,更新最大值即可。
证明:
假设存在一个圆,圆内包含了最大个数的点,稍微移动圆的圆心不会发生任何变化,直到移动至出现两个点在圆上时,最大值依旧没有发生变化,但一旦再移动时,最大个数将减小。所以最大值一定存在于某两个点i和j构成的圆,且i和j在圆上or圆内。
参考至:
http://www.hankcs.com/program/algorithm/poj-1981-circle-and-points.html
所以我们只需要计算出两个点构成的极角,当然都得以i为坐标原点。
- atan2的角度为j和i的纵坐标与横坐标之比,取反tan。
- acos的角度为d/2,图中很清楚了。
- 所以两个极限角即为atan2 - acos和atan2 + acos。
最后,对极角排个序,遇到起始点加1,遇到终点减1,不断更新重叠区域个数的最大值即可。
代码如下:
import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.util.Arrays;import java.util.StringTokenizer;public class Main{ String INPUT = "./data/judge/201709/P1981.txt"; public static void main(String[] args) throws IOException { new Main().run(); } static final int MAX_N = 302; class P { double x; double y; P(double x, double y){ this.x = x; this.y = y; } } class PolarAngle implements Comparable<PolarAngle>{ double angle; boolean flag; PolarAngle(double angle, boolean flag){ this.angle = angle; this.flag = flag; } @Override public int compareTo(PolarAngle that) { return Double.compare(this.angle, that.angle); } } P[] points = new P[MAX_N]; PolarAngle[] pa = new PolarAngle[2 * MAX_N]; int N; int ans; double dist(P a, P b) { double dx = a.x - b.x; double dy = a.y - b.y; return Math.sqrt(dx * dx + dy * dy); } void solve() { ans = 1; for (int i = 0; i < N; ++i) { int m = 0; for (int j = 0; j < N; ++j) { double d = 0; if (i != j && (d = dist(points[i], points[j])) <= 2.0) { double theta = Math.acos(d / 2); double phi = Math.atan2(points[j].y - points[i].y, points[j].x - points[i].x); pa[m++] = new PolarAngle(phi - theta, true); // start pa[m++] = new PolarAngle(phi + theta, false); // end; } } Arrays.sort(pa, 0, m); int sum = 1; for (int j = 0; j < m; ++j) { if (pa[j].flag) { sum ++; } else { sum --; } ans = Math.max(ans, sum); } } } void read() { while (true) { N = ni(); if (N == 0) break; for (int i = 0; i < N; ++i) { points[i] = new P(nd(), nd()); } ans = 0; solve(); out.println(ans); } } FastScanner in; PrintWriter out; void run() throws IOException { boolean oj; try { oj = ! System.getProperty("user.dir").equals("F:\\java_workspace\\leetcode"); } catch (Exception e) { oj = System.getProperty("ONLINE_JUDGE") != null; } InputStream is = oj ? System.in : new FileInputStream(new File(INPUT)); in = new FastScanner(is); out = new PrintWriter(System.out); long s = System.currentTimeMillis(); read(); out.flush(); if (!oj){ System.out.println("[" + (System.currentTimeMillis() - s) + "ms]"); } } public boolean more(){ return in.hasNext(); } public int ni(){ return in.nextInt(); } public long nl(){ return in.nextLong(); } public double nd(){ return in.nextDouble(); } public String ns(){ return in.nextString(); } public char nc(){ return in.nextChar(); } class FastScanner { BufferedReader br; StringTokenizer st; boolean hasNext; public FastScanner(InputStream is) throws IOException { br = new BufferedReader(new InputStreamReader(is)); hasNext = true; } public String nextToken() { while (st == null || !st.hasMoreTokens()) { try { st = new StringTokenizer(br.readLine()); } catch (Exception e) { hasNext = false; return "##"; } } return st.nextToken(); } String next = null; public boolean hasNext(){ next = nextToken(); return hasNext; } public int nextInt() { if (next == null){ hasNext(); } String more = next; next = null; return Integer.parseInt(more); } public long nextLong() { if (next == null){ hasNext(); } String more = next; next = null; return Long.parseLong(more); } public double nextDouble() { if (next == null){ hasNext(); } String more = next; next = null; return Double.parseDouble(more); } public String nextString(){ if (next == null){ hasNext(); } String more = next; next = null; return more; } public char nextChar(){ if (next == null){ hasNext(); } String more = next; next = null; return more.charAt(0); } }}
阅读全文
0 0
- 挑战程序竞赛系列(84):3.6极限情况(1)
- 挑战程序竞赛系列(85):3.6极限情况(2)
- 挑战程序竞赛系列(86):3.6极限情况(3)
- 挑战程序竞赛系列(83):3.6计算几何基础
- 挑战程序竞赛系列(81):4.3 LCA(1)
- 挑战程序竞赛系列(1):2.3动态规划
- 挑战程序竞赛系列(87):3.6平面扫描(1)
- 挑战程序竞赛系列(90):3.6凸包(1)
- 挑战程序竞赛系列(95):3.6数值积分(1)
- 挑战程序竞赛系列(82):4.3 LCA(2)
- 挑战程序竞赛系列(4):2.1深度优先搜索
- 挑战程序竞赛系列(5):2.1广度优先搜索
- 挑战程序竞赛系列(6):2.1穷尽搜索
- 挑战程序竞赛系列(9):2.4优先队列
- 挑战程序竞赛系列(10):2.4并查集
- 挑战程序竞赛系列(11):2.5最短路径
- 挑战程序竞赛系列(12):2.5最小生成树
- 挑战程序竞赛系列(13):2.6辗转相除法
- Spring 源码解析之ViewResolver源码解析(四)
- android学习笔记(三)
- 百度竞价赚钱攻略,揭秘竞价不公开的秘密
- 初心不改,始终如一
- 有哪些好习惯可以坚持
- 挑战程序竞赛系列(84):3.6极限情况(1)
- 构造方法的重载
- 360Lib:CPP-PSNR
- 滑动窗口的最大值
- 494. Target Sum
- Esper中使用枚举类型作为过滤条件的语法
- Xamarin 卫星菜单(Satellite Menu)组件使用案例!目前只兼容Android、iOS(二)
- sentry
- 非线程安全类ArrayList出现异常:java.util.ConcurrentModificationException