挑战程序竞赛系列(94):3.6凸包(5)
2017-10-16 17:33
495 查看
挑战程序竞赛系列(94):3.6凸包(5)
传送门:POJ 2079: Triangle题意:
求三个点构成的最大三角形面积。
思路:
可以证明,三点构成的最大三角形面积一定在凸包上,传统算法for循环三次,时间复杂度为O(n3),实际上可以把复杂度降为O(n2)。对于给定的两点(P, Q),求得第三点R,使得PQR的三角形面积最大。
性质1:
因为凸包上满足性质:循环遍历R时,三角形面积先增后减,找到最大即可停止搜索。
性质2:
利用(P, Q)求得的点R,在搜索(Q, Q_next)的最大三角形面积时,可以从点R开始继续向后搜索,而不需要从头开始。
综上,时间复杂度降为O(n2)。
代码如下:
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.Map; import java.util.StringTokenizer; public class Main{ String INPUT = "./data/judge/201710/P2079.txt"; public static void main(String[] args) throws IOException { new Main().run(); } class P implements Comparable<P>{ int x; int y; P(int x, int y){ this.x = x; this.y = y; } P sub(P a) { return new P(x - a.x, y - a.y); } int det(P a) { return x * a.y - y * a.x; } @Override public int compareTo(P o) { return x - o.x != 0 ? x - o.x : y - o.y; } } int N; P[] p; double area(P a, P b, P c) { double ans = (c.x - a.x) * (b.y - a.y) - (c.y - a.y) * (b.x - a.x); return 0.5 * Math.abs(ans); } P[] convexHull() { Arrays.sort(p); P[] qs = new P[2 * N]; int k = 0; for (int i = 0; i < N; ++i) { while (k > 1 && qs[k - 1].sub(qs[k - 2]).det(p[i].sub(qs[k - 2])) < 0) k --; qs[k++] = p[i]; } for (int i = N - 2, t = k; i >= 0; --i) { while (k > t && qs[k - 1].sub(qs[k - 2]).det(p[i].sub(qs[k - 2])) < 0) k--; qs[k++] = p[i]; } P[] res = new P[k - 1]; System.arraycopy(qs, 0, res, 0, k - 1); return res; } void solve() { P[] qs = convexHull(); int n = qs.length; double ans = 0; for (int offset = 1; offset < (n + 1) / 2; ++offset) { int fir = 0; int pos = (fir + offset + 1) % n; do { int sec = (fir + offset) % n; while ((pos + 1) % n != fir && area(qs[fir % n], qs[sec % n], qs[(pos + 1) % n]) >= area(qs[fir % n], qs[sec % n], qs[pos % n])) { pos = (pos + 1) % n; } ans = Math.max(ans, area(qs[fir % n], qs[sec % n], qs[pos % n])); fir = (fir + 1) % n; } while (fir != 0); } out.printf("%.2f\n", ans); } void read() { while (true) { N = ni(); if (N == -1) break; p = new P ; for (int i = 0; i < N; ++i) { p[i] = new P(ni(), ni()); } solve(); } } FastScanner in; PrintWriter out; void run() throws IOException { boolean oj; try { oj = ! System.getProperty("user.dir").equals("F:\\oxygen_workspace\\Algorithm"); } 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); } } }
相关文章推荐
- 挑战程序竞赛系列(93):3.6凸包(4)
- 挑战程序竞赛系列(90):3.6凸包(1)
- 挑战程序竞赛系列(91):3.6凸包(2)
- 挑战程序竞赛系列(92):3.6凸包(3)
- 挑战程序竞赛系列(86):3.6极限情况(3)
- 挑战程序竞赛系列(6):2.1穷尽搜索
- 挑战程序竞赛系列(43):4.1矩阵 高斯消元
- 挑战程序竞赛系列(1):2.3动态规划
- 挑战程序竞赛系列(63):4.7字符串上的动态规划(1)
- 挑战程序竞赛系列(25):3.5最大权闭合图
- 挑战程序竞赛系列(18):3.1查找第k大的值
- 挑战程序竞赛系列(19):3.1最小化第k大的值
- 挑战程序竞赛系列(47):4.1 计数 二项式取模
- 挑战程序竞赛系列(34):3.2坐标离散化
- 挑战程序竞赛系列(75):4.3强连通分量分解(2)
- 挑战程序竞赛系列(31):4.5剪枝
- 挑战程序竞赛系列(23):3.2折半枚举
- 挑战程序竞赛系列(73):4.7高度数组(3)
- 挑战程序竞赛系列(83):3.6计算几何基础
- 挑战程序竞赛系列(85):3.6极限情况(2)