• POJ2451 Uyuw's Concert(半平面交)


    题意就是给你很多个半平面,求半平面交出来的凸包的面积。

    半平面交有O(n^2)的算法,就是每次用一个新的半平面去切已有的凸包,更新,这个写起来感觉也不是特别好写。

    另外一个O(nlogn)的算法是将半平面交极角排序,然后用一个双端队列去维护半平面交,每次加入一个半平面,根据之前的交点的位置退掉半平面,方法跟凸包非常相像,(不同的是加入队列的时候还要考虑加入半平面会使队首的平面变得无效,因为会有两个while.最后还要考虑最后加入的半平面绕了一圈之后使得队首的半平面变得无效。)其实这里有点不太懂后面再慢慢补一补吧。

    下面的代码用的是CLJ的模板,看大神写的模板能学习到很多东西。我对于计算几何还是不太熟悉,因为如何利用cross求很多东西其实都不太熟,例如如何用cross求两直线的交点。还有里面的border的极角排序的<重载,unique去重时需要的==重载。更高深的原理日后慢慢研究。。- -0

    #pragma warning(disable:4996)
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <string>
    #include <algorithm>
    using namespace std;
    
    #define maxn 25000
    #define eps 1e-8
    
    int n;
    
    int dcmp(double x){
    	return (x > eps) - (x < -eps);
    }
    
    struct Point
    {
    	double x, y;
    	Point(){}
    	Point(double _x, double _y) :x(_x), y(_y){}
    	Point operator + (const Point &b) const{
    		return Point(x + b.x, y + b.y);
    	}
    	Point operator - (const Point &b) const{
    		return Point(x - b.x, y - b.y);
    	}
    	Point operator *(double d) const{
    		return Point(x*d, y*d);
    	}
    	Point operator /(double d) const{
    		return Point(x / d, y / d);
    	}
    	double det(const Point &b) const{
    		return x*b.y - y*b.x;
    	}
    	double dot(const Point &b) const{
    		return x*b.x + y*b.y;
    	}
    };
    
    #define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
    #define crossOp(p1,p2,p3) (dcmp(cross(p1,p2,p3)))
    
    Point isSS(Point p1, Point p2, Point q1, Point q2){
    	double a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
    	return (p1*a2 + p2*a1) / (a1 + a2);
    }
    
    struct Border
    {
    	Point p1, p2;
    	double alpha;
    	void setAlpha(){
    		alpha = atan2(p2.y - p1.y, p2.x - p1.x);
    	}
    	bool operator < ( const Border &b) const{
    		int c = dcmp(alpha - b.alpha);
    		if (c != 0) return c == 1;
    		return crossOp(b.p1, b.p2, p1) >= 0;
    	}
    	bool operator == (const Border &b) const{
    		return dcmp(alpha - b.alpha) == 0;
    	}
    };
    
    
    Point isBorder(const Border &a, const Border &b){
    	return isSS(a.p1, a.p2, b.p1, b.p2);
    }
    
    Border border[maxn];
    Border que[maxn];
    int qh, qt;
    // check函数判断的是新加的半平面和由a,b两个半平面产生的交点的方向,若在半平面的左侧返回True
    bool check(const Border &a, const Border &b,const Border &me){
    	Point is = isBorder(a, b);
    	return crossOp(me.p1, me.p2, is) > 0;
    }
    
    void convexIntersection()
    {
    	qh = qt = 0;
    	sort(border, border + n);
    	n = unique(border, border + n) - border;
    	for (int i = 0; i < n; i++){
    		Border cur = border[i];
    		while (qh + 1 < qt&&!check(que[qt - 2], que[qt - 1], cur)) --qt;
    		while (qh + 1 < qt&&!check(que[qh], que[qh + 1], cur)) ++qh;
    		que[qt++]=cur;
    	}
    	while (qh + 1 < qt&&!check(que[qt - 2], que[qt - 1], que[qh])) --qt;
    	while (qh + 1 < qt&&!check(que[qh], que[qh + 1], que[qt-1])) ++qh;
    }
    
    Point ps[maxn];
    
    int main()
    {
    	while (cin >> n)
    	{
    		for (int i = 0; i < n; i++){
    			scanf("%lf%lf%lf%lf", &border[i].p1.x, &border[i].p1.y, &border[i].p2.x, &border[i].p2.y);
    		}
    		border[n].p1.x = 0; border[n].p1.y = 0; border[n].p2.x = 10000; border[n].p2.y = 0;
    		border[n+1].p1.x = 10000; border[n+1].p1.y = 0; border[n+1].p2.x = 10000; border[n+1].p2.y = 10000;
    		border[n+2].p1.x = 10000; border[n+2].p1.y = 10000; border[n+2].p2.x = 0; border[n+2].p2.y = 10000;
    		border[n+3].p1.x = 0; border[n+3].p1.y = 10000; border[n+3].p2.x = 0; border[n+3].p2.y = 0;
    		n = n + 4;
    		for (int i = 0; i < n; i++){
    			border[i].setAlpha();
    		}
    		convexIntersection();
    		int cnt = 0;
    		if (qt - qh <= 2){
    			puts("0.0"); continue;
    		}
    		for (int i = qh; i < qt; i++){
    			int nxt = i + 1 == qt ? qh : i + 1;
    			ps[cnt++] = isBorder(que[i], que[nxt]);
    		}
    		double area = 0;
    		for (int i = 0; i < cnt; i++){
    			area += ps[i].det(ps[(i + 1) % cnt]);
    		}
    		area /= 2;
    		area = fabs(area);
    		printf("%.1lf
    ", area);
    	}
    	return 0;
    }
    
  • 相关阅读:
    tensorboard使用命令
    FFmpeg安装以及视频转成图片_图片转成视频_以及分辨率转换
    yolo3各部分代码详解(超详细)
    OpenCV+python 彩色图像通道拆分与组合并判断size,shape函数的用法与区别
    基于Keras 的VGG16神经网络模型的Mnist数据集识别并使用GPU加速
    以Mnist为例从头开始自己建立数据集,搭建resnet34,识别Mnist
    2017年Brats 脑肿瘤挑战赛Automatic Brain Tumor Segmentation using Cascaded Anisotropic Convolutional Neural Networks
    2018年BRATS 肿瘤分割挑战赛第三名分割方案One-pass Multi-task Networks with Cross-task Guided Attention for Brain Tumor Segmentation
    脑胶质瘤论文笔记
    .npy文件的保存与加载
  • 原文地址:https://www.cnblogs.com/chanme/p/3708303.html
Copyright © 2020-2023  润新知