zoukankan      html  css  js  c++  java
  • [CQOI2006]凸多边形

    一年前写的代码现在已经惨不忍睹了,趁着 olinr讲计算几何,再打一遍板子。

    半平面交的步骤是:

    1. 将所有半平面极角排序

    2. 维护一个双端队列,按照极角序更新首尾的半平面,然后插入半平面

    3. 最后再将首尾更新一次

    最后队列里所有的半平面即为答案。

    下面是重写后的代码,感觉好看多了~

    #include <bits/stdc++.h>
    using namespace std;
    
    const double eps  = 1e-6;
    
    struct Vector
    {
    	double x, y;
    	Vector(double x = 0, double y = 0) : x(x), y(y) {}
    	double mod() {return sqrt(x * x + y * y);}
    };
    
    struct Line
    {
    	Vector p, v;
    }a[510];
    
    int n, nn;
    
    Vector operator+(const Vector &a, const Vector &b) {return Vector(a.x + b.x, a.y + b.y);}
    Vector operator-(const Vector &a, const Vector &b) {return Vector(a.x - b.x, a.y - b.y);}
    Vector operator*(const Vector &a, const double &b) {return Vector(a.x * b, a.y * b);}
    Vector operator/(const Vector &a, const double &b) {return Vector(a.x / b, a.y / b);}
    Vector operator*(const double &a, const Vector &b) {return Vector(a * b.x, a * b.y);}
    double operator*(const Vector &a, const Vector &b) {return a.x * b.x + a.y * b.y;}
    double operator^(const Vector &a, const Vector &b) {return a.x * b.y - a.y * b.x;}
    
    bool polar_cmp(const Line &a, const Line &b)
    {
    	if (fabs(atan2(a.v.y, a.v.x) - atan2(b.v.y, b.v.x)) > eps)
    		return atan2(a.v.y, a.v.x) < atan2(b.v.y, b.v.x);
    	return (a.v ^ (b.p - a.p)) < 0;
    }
    
    Vector inter(const Line &a, const Line &b)
    {
    	return b.p + b.v * (((b.p - a.p) ^ a.v) / (a.v ^ b.v));
    }
    
    void input_poly()
    {
    	int m, x[55], y[55];
    	scanf("%d", &m);
    	for (int i = 1; i <= m; i++)
    		scanf("%d%d", &x[i], &y[i]);
    	x[m + 1] = x[1], y[m + 1] = y[1];
    	for (int i = 1; i <= m; i++)
    		a[++nn].p = Vector(x[i], y[i]), a[nn].v = Vector(x[i + 1] - x[i], y[i + 1] - y[i]);
    }
    
    Line q[2333];
    Vector li[2333];
    int top, bottom;
    
    bool valid(const Vector p, const Line &l)
    {
    	return (l.v ^ (p - l.p)) > 0;
    }
    
    void insert(const Line &l)
    {
    	while (top - bottom >= 2 && valid(inter(q[top], q[top - 1]), l) == false)
    		top--;
    	while (top - bottom >= 2 && valid(inter(q[bottom + 1], q[bottom + 2]), l) == false)
    		bottom++;
    	q[++top] = l;
    }
    
    int main()
    {
    	int fuck;
    	scanf("%d", &fuck);
    	for (int i = 1; i <= fuck; i++)
    		input_poly();
    	sort(a + 1, a + 1 + nn, polar_cmp);
    	for (int i = 1; i <= nn; i++)
    		if (i == 1 || fabs(atan2(a[i].v.y, a[i].v.x) - atan2(a[i - 1].v.y, a[i - 1].v.x)) > eps)
    			a[++n] = a[i];
    	for (int i = 1; i <= n; i++)
    		insert(a[i]);
    	while (top - bottom >= 2 && valid(inter(q[top], q[top - 1]), q[bottom + 1]) == false)
    		top--;
    	while (top - bottom >= 2 && valid(inter(q[bottom + 1], q[bottom + 2]), q[top]) == false)
    		bottom++;
    	q[bottom] = q[top];
    	for (int i = bottom; i < top; i++)
    		li[i] = inter(q[i], q[i + 1]);
    	li[top] = li[bottom];
    	double res = 0;
    	for (int i = bottom; i < top; i++)
    		res += (li[i] ^ li[i + 1]);
    	printf("%.3f
    ", res / 2);
    	return 0;
    }
    
  • 相关阅读:
    git apply、git am打补丁.diff 和 .patch【转】
    RK3288 GPIO 输出问题【转】
    [RK3288][Android6.0] 调试笔记 --- 通用GPIO驱动控制LED【转】
    [RK3288][Android6.0] 调试笔记 --- 系统识别不同硬件版本方法【转】
    Android驱动开发之earlysuspend睡眠模式--实现代码【转】
    触摸屏唤醒实现【转】
    强加密RNGCryptoServiceProvider
    java中有类似C#里ref或out的功能吗?
    mysql中char与varchar的区别分析
    JVM再了解了解
  • 原文地址:https://www.cnblogs.com/oier/p/10217818.html
Copyright © 2011-2022 走看看